Poradnik Scali

Podsumowanie samouczka Scali

Ten tutorial scala omawia wszystkie aspekty i tematy scala. Nauczysz siฤ™ od podstaw wszystkich podstaw, takich jak czym jest scala, proces instalacji scala, programy Scala, funkcje Scala, leniwa ocena, interfejs typรณw, klasy i obiekty, dziedziczenie, abstrakcje, Java i rรณลผnice w skalach itp.

Czym jest Scala?

Scala jest statycznie typowanym jฤ™zykiem programowania, ktรณry ล‚ฤ…czy w sobie zarรณwno programowanie funkcjonalne, jak i obiektowe, aby zwiฤ™kszyฤ‡ skalowalnoล›ฤ‡ aplikacji. Scala dziaล‚a gล‚รณwnie na platformie JVM i moลผe byฤ‡ rรณwnieลผ uลผywana do pisania oprogramowania na natywne platformy przy uลผyciu Scala-Native i JAVASCRIPT ล›rodowiska uruchomieniowe poprzez ScalaJs.

Scala to skalowalny jฤ™zyk uลผywany do pisania oprogramowania na wiele platform. Stฤ…d wziฤ™ล‚a siฤ™ nazwa โ€žScalaโ€. Jฤ™zyk ten ma na celu rozwiฤ…zywanie problemรณw Java jednoczeล›nie bฤ™dฤ…c bardziej zwiฤ™zล‚ym. Poczฤ…tkowo zaprojektowany przez Martina Odersky'ego, zostaล‚ wydany w 2003 roku.

Dlaczego warto uczyฤ‡ siฤ™ Scali

Oto gล‚รณwne powody, dla ktรณrych warto uczyฤ‡ siฤ™ jฤ™zyka programowania Scala:

  • Scala jest ล‚atwa do nauczenia dla programistรณw obiektowych, Java deweloperzy. W ostatnich latach staje siฤ™ jednym z najpopularniejszych jฤ™zykรณw.
  • Scala oferuje uลผytkownikom najwyลผszej klasy funkcje
  • Scala moลผe byฤ‡ wykonywana na FMV, torujฤ…c w ten sposรณb drogฤ™ do interoperacyjnoล›ci z innymi jฤ™zykami.
  • Jest przeznaczony dla aplikacji wspรณล‚bieลผnych, rozproszonych i odpornych na dziaล‚anie komunikatรณw. Jest to jeden z najbardziej wymagajฤ…cych jฤ™zykรณw tej dekady.
  • Jest to zwiฤ™zล‚y, mocny jฤ™zyk i moลผe szybko rosnฤ…ฤ‡ w zaleลผnoล›ci od potrzeb uลผytkownikรณw.
  • Jest zorientowany obiektowo i ma wiele funkcjonalnych funkcji programistycznych, zapewniajฤ…cych programistom duลผฤ… elastycznoล›ฤ‡ w zakresie kodowania w taki sposรณb, w jaki chcฤ….
  • Scala oferuje wiele typรณw kaczek
  • Ma mniej szablonรณw, jeล›li pochodzisz Java
  • Frameworki Lift and Play napisane w Scali sฤ… w fazie wzrostu.

Jak zainstalowaฤ‡ Scalฤ™

Aby rozpoczฤ…ฤ‡ pisanie programรณw w jฤ™zyku Scala, musisz mieฤ‡ go zainstalowany na swoim komputerze. Aby to zrobiฤ‡, musisz odwiedziฤ‡ ich witrynฤ™ https://www.scala-lang.org/download/ w celu pobrania najnowszej wersji Scali.

Po klikniฤ™ciu ล‚ฤ…cza zostanฤ… nam wyล›wietlone dwie opcje, ktรณre moลผemy wybraฤ‡, aby zainstalowaฤ‡ Scalฤ™ na naszych komputerach. W tym samouczku Scala pobierzemy IntelliJ IDEA.

Jak zainstalowaฤ‡ Scalฤ™

Po odwiedzeniu ล‚ฤ…cza pobierania znajdziesz dwie wersje IntelliJ IDE.

Na potrzeby tego samouczka dotyczฤ…cego jฤ™zyka Scala pobierzemy wersjฤ™ Community Edition, ktรณra jest bezpล‚atna i zawiera wszystko, co potrzebne do pisania programรณw w jฤ™zyku Scala.

Jak zainstalowaฤ‡ Scalฤ™

Krok 1) Wybierz wersjฤ™ Community
Na stronie kliknij menu rozwijane Community Edition.

Daje nam moลผliwoล›ฤ‡ pobrania IntelliJ IDE razem z JBR, ktรณry zawiera implementacjฤ™ JDK (Java Development Kit) OpenJDK, ktรณrego Scala potrzebuje do skompilowania i uruchomienia kodu.

Jak zainstalowaฤ‡ Scalฤ™

Krok 2) Uruchom instalacjฤ™
Po pobraniu programu IntelliJ kliknij go dwukrotnie, aby uruchomiฤ‡ kreatora instalacji, i postฤ™puj zgodnie z instrukcjami.

Jak zainstalowaฤ‡ Scalฤ™

Krok 3) Wybierz lokalizacjฤ™
Wybierz lokalizacjฤ™, w ktรณrej chcesz zainstalowaฤ‡ IDE.

Jak zainstalowaฤ‡ Scalฤ™

Jeล›li nie pobraล‚eล› wersji z pakietem JDK, i tak pojawi siฤ™ monit, w ktรณrym naleลผy zaznaczyฤ‡ pole wyboru, aby zaznaczyฤ‡ opcjฤ™ pobrania.

Jak zainstalowaฤ‡ Scalฤ™

Krok 4) Kliknij dalej
Pozostaw pozostaล‚e ustawienia domyล›lne bez zmian i kliknij Dalej.

Jak zainstalowaฤ‡ Scalฤ™

Krok 5) Kliknij ikonฤ™ uruchamiania
Po zakoล„czeniu instalacji uruchom IntelliJ IDE, klikajฤ…c jego ikonฤ™ uruchamiania w menu startowym, jak zwykล‚ฤ… aplikacjฤ™.

Jak zainstalowaฤ‡ Scalฤ™

Nadal musisz przejล›ฤ‡ dodatkowy etap dodania wtyczki Scala do IntelliJ; robisz to poprzez klikniฤ™cie rozwijanego menu konfiguracji znajdujฤ…cego siฤ™ w prawym dolnym rogu ekranu i wybranie opcji wtyczki.

Jak zainstalowaฤ‡ Scalฤ™

Jak zainstalowaฤ‡ Scalฤ™

Na karcie Rynek, wyszukiwanie Scala wyล›wietli wtyczkฤ™ jako pierwszy wynik pod tagiem Jฤ™zyki.

Krok 6) Zainstaluj wtyczkฤ™
Kliknij przycisk instaluj, co spowoduje rozpoczฤ™cie pobierania wtyczki.

Jak zainstalowaฤ‡ Scalฤ™

Krok 7) Uruchom ponownie IDE
Po zakoล„czeniu pobierania zostaniesz poproszony o ponowne uruchomienie IDE, aby zainstalowana wtyczka mogล‚a zaczฤ…ฤ‡ dziaล‚aฤ‡.

Jak zainstalowaฤ‡ Scalฤ™

Po ponownym uruchomieniu znajdziesz siฤ™ na tej samej stronie, co poprzednio, kiedy uruchamialiล›my IDE, ale tym razem zainstalowaliล›my juลผ wtyczkฤ™ Scala.

Program Scala Hello World

Krok 1) Wybierz opcjฤ™ Utwรณrz projekt, co przeniesie nas na stronฤ™, na ktรณrej moลผemy wybraฤ‡ rodzaj jฤ™zyka, w jakim bฤ™dzie uลผywany nasz projekt.

Program Scala Hello World

Krok 2) wybierz Scalฤ™ zaznaczajฤ…c pole wyboru Scala i kliknij Dalej.

Program Scala Hello World

Krok 3) Wybierz lokalizacjฤ™, w ktรณrej chcesz zapisaฤ‡ plik naszego projektu i nadaj naszemu projektowi nazwฤ™.

Program Scala Hello World

Jeล›li katalog nie istnieje, IntelliJ poprosi nas o pozwolenie na utworzenie folderu. Zaakceptuj i kliknij Zakoล„cz. Zostaniesz przeniesiony do projektu Scala, ktรณry obecnie nie ma ลผadnego kodu Scala.

Zaล‚adowanie niektรณrych indeksรณw zajmie trochฤ™ czasu, wiฤ™c nie martw siฤ™, jeล›li nie moลผesz od razu nic zrobiฤ‡, gdy na dole IDE znajduje siฤ™ pasek postฤ™pu. Oznacza to po prostu, ลผe IDE ล‚aduje niektรณre pliki niezbฤ™dne do uruchomienia Scali i pomoc w autouzupeล‚nianiu IDE.

Krok 4) Nastฤ™pnie klikniemy kartฤ™ projektรณw po lewej stronie IDE i rozwiniemy jฤ…, abyล›my mogli zobaczyฤ‡ zawartoล›ฤ‡ naszego projektu.

Program Scala Hello World

W tej chwili projekt jest pusty i zawiera jedynie folder .idea i plik hello-world.iml wygenerowany przez IDE. Nas interesuje folder src. Src to miejsce, w ktรณrym przechowujemy kod ลบrรณdล‚owy naszego projektu. Tutaj utworzymy nasz pierwszy plik Scala.

Krok 5) Kliknij prawym przyciskiem myszy src, aby otworzyฤ‡ menu umoลผliwiajฤ…ce utworzenie nowego pliku Scala.

Utwรณrz nowy plik Scala

Nastฤ™pnie utworzymy nazwฤ™ pliku. W tym samouczku dotyczฤ…cym Scali uลผyjemy sล‚owa hello, a nastฤ™pnie z listy rozwijanej wybierzemy, co umieล›ciฤ‡ jako zawartoล›ฤ‡ pliku Scala. Wybierz โ€žObiektโ€

Program Scala Hello World

Gdy to zrobimy, bฤ™dziemy mieli plik Scala zawierajฤ…cy obiekt Singleton, ktรณrego uลผyjemy do uruchomienia naszego kodu.

Program Scala Hello World

Teraz, gdy masz plik Scala z obiektem Hello. Swรณj pierwszy program napiszesz rozszerzajฤ…c utworzony obiekt za pomocฤ… sล‚owa kluczowego App.

Rozszerzajฤ…c nasz obiekt o aplikacjฤ™, powiedz kompilatorowi, ktรณry kod ma zostaฤ‡ uruchomiony podczas uruchamiania programu. Natychmiast po rozszerzeniu aplikacji po lewej stronie pojawi siฤ™ zielona strzaล‚ka wskazujฤ…ca, ลผe โ€‹โ€‹moลผesz teraz uruchomiฤ‡ swรณj program.

Program Scala Hello World

Program Scala Hello World

Wewnฤ…trz obiektu Hello piszemy jednฤ… funkcjฤ™ println(), ktรณra sล‚uลผy do wypisywania znajdujฤ…cego siฤ™ w nim tekstu na konsoli. Uruchomimy nasz kod klikajฤ…c na zielonฤ… strzaล‚kฤ™.

Klikniฤ™cie strzaล‚ki powoduje wyล›wietlenie opcji Uruchom, witaj, po klikniฤ™ciu nasz kod zacznie siฤ™ kompilowaฤ‡ i po kilku sekundach zobaczymy wyniki dziaล‚ania naszego programu wydrukowane z konsoli wbudowanej w IntelliJ IDE.

Program Scala Hello World

I gotowe, pomyล›lnie zainstalowaliล›my Scalฤ™ i uruchomiliล›my nasz pierwszy program.

Co moลผesz zrobiฤ‡ ze Scalฤ…

  • Tworzenie frontendowych stron internetowych w ScalaJS
  • Rozwรณj mobilny, oba Android Rozwรณj i IOS โ€“ z Scala Native
  • Biblioteki po stronie serwera, takie jak HTTP4S, Akka-Http, Play Framework
  • Korzystanie z Internetu rzeczy
  • Produkcja gier
  • NLP โ€“ przetwarzanie jฤ™zyka naturalnego z wykorzystaniem pakietu bibliotek ScalaNLP
  • Testowanie zaawansowanych technik programowania, takich jak programowanie funkcyjne i programowanie obiektowe
  • Zbuduj wysoce wspรณล‚bieลผnฤ… aplikacjฤ™ komunikacyjnฤ…, korzystajฤ…c z aktorรณw i biblioteki dla JVM inspirowanej Erlangiem
  • Uลผyj go do uczenia maszynowego przy uลผyciu bibliotek takich jak Figaro, ktรณre programuje probabilistycznie i Apache Spark ลผe

Funkcje anonimowe

Jฤ™zyk Scala ma funkcje anonimowe, ktรณre sฤ… rรณwnieลผ nazywane literaล‚y funkcyjne. Scala jako jฤ™zyk funkcjonalny czฤ™sto oznacza, ลผe โ€‹โ€‹programiล›ci dzielฤ… duลผe problemy na wiele maล‚ych zadaล„ i tworzฤ… wiele funkcji w celu rozwiฤ…zania tych problemรณw. Aby uล‚atwiฤ‡ tworzenie funkcji, Scala zawiera te funkcje, ktรณre moลผna utworzone bez nazwy. Moลผemy je przypisaฤ‡ bezpoล›rednio do zmiennych lub definicji โ€ždefโ€, jak pokazano na poniลผszym przykล‚adzie w Scali:

val multiplyByTwo = (n:Int) => n * 2
def multiplyByThree = (n:Int) => n *3

Nastฤ™pnie moลผemy uลผywaฤ‡ funkcji w zwykล‚y sposรณb, przekazujฤ…c im parametry.

multiplyByTwo(3)

//6

multiplyByThree(4)

//12

Metody te przydadzฤ… siฤ™, gdy chcemy mieฤ‡ czysty i zwiฤ™zล‚y kod. Funkcji anonimowych moลผemy uลผywaฤ‡ przy definiowaniu metod, ktรณre nie sฤ… duลผe i nie wymagajฤ… duลผej iloล›ci kodu w swojej treล›ci. Sฤ… bardzo proste i nie wymagajฤ… ceremonii przy ich tworzeniu.

Metody te nie ograniczajฤ… siฤ™ do funkcji z argumentami i moลผna ich uลผywaฤ‡ do tworzenia instancji metod, ktรณre nie przyjmujฤ… ลผadnych argumentรณw.

val sayHello = ()=>{ println("hello") }

Wiฤ™kszoล›ฤ‡ tych anonimowych funkcji jest uลผywana w innych czฤ™ล›ciach naszego kodu, w ktรณrych musimy utworzyฤ‡ szybkฤ… funkcjฤ™.

Innym powodem, dla ktรณrego te funkcje sฤ… rรณwnieลผ okreล›lane jako funkcje wbudowane. Korzystanie z funkcji anonimowych to powszechny wzorzec powszechnie uลผywany w bibliotece kolekcji do wykonywania szybkich dziaล‚aล„ na kolekcji.

Na przykล‚ad mamy metodฤ™ filter, ktรณra wykorzystuje funkcjฤ™ wbudowanฤ…/funkcjฤ™ anonimowฤ…, aby utworzyฤ‡ kolejnฤ… kolekcjฤ™ zawierajฤ…cฤ… tylko elementy speล‚niajฤ…ce kryteria zdefiniowane przez nas w funkcji anonimowej.

val myList = List(1,2,3,4,5,6,7)

val myEvenList = myList.filter((n: Int) => n % 2 == 0)
//List(2,4,6)

val myOddList = myList.filter((n:Int) => n % 2 != 0)
//List(1,3,5,7)

Tutaj metody, ktรณre mamy jako funkcje anonimowe, to te, ktรณre sprawdzajฤ…, czy wartoล›ฤ‡, ktรณrฤ… otrzymujemy z listy, sฤ… nieparzyste i parzyste, i zwracajฤ… element.

//the one checking that the value is even
(n: Int) => n % 2 == 0

//the one checking that the value is odd
(n:Int) => n % 2 != 0

W Scali moลผna takลผe uลผywaฤ‡ symboli wieloznacznych tam, gdzie nie ma nazwy parametrรณw naszej funkcji anonimowej. Na przykล‚ad

var timesTwo = (_:Int)*2

timesTwo(5)
//10

W tym scenariuszu nie nazywamy parametru, ktรณry przekazujemy. Jedyne, co reprezentujemy, to podkreล›lenie.

Leniwa ocena

Wiฤ™kszoล›ฤ‡ jฤ™zykรณw ocenia zmienne i parametry funkcji sekwencyjnie, jeden po drugim. W Scali mamy sล‚owo kluczowe o nazwie lazy, ktรณre pomaga w radzeniu sobie z wartoล›ciami, do ktรณrych nie chcemy byฤ‡ oceniani, dopรณki siฤ™ do nich nie odwoล‚amy.

Zmienna oznaczona jako leniwa nie bฤ™dzie oceniana w miejscu, w ktรณrym zostaล‚a zdefiniowana. Jest to powszechnie znane jako ocenianie chฤ™tne. Zmienna bฤ™dzie oceniana dopiero w momencie odwoล‚ania siฤ™ do niej w dalszej czฤ™ล›ci kodu.

Moลผe to byฤ‡ pomocne, gdy ocena wartoล›ci moลผe byฤ‡ kosztownym obliczeniem. Jeล›li nie jest tak, ลผe wartoล›ฤ‡ jest zawsze potrzebna, moลผemy uniknฤ…ฤ‡ wykonywania kosztownych obliczeล„, ktรณre mogฤ… spowolniฤ‡ nasze oprogramowanie poprzez spowolnienie naszej zmiennej.

lazy val myExpensiveValue = expensiveComputation

def runMethod()={
    if(settings == true){
        use(myExpensiveValue)
    }else{
        use(otherValue)
    }
}

Nie jest to jedyny przypadek uลผycia leniwych zmiennych. Pomagajฤ… takลผe w rozwiฤ…zywaniu problemรณw zwiฤ…zanych z zaleลผnoล›ciฤ… cyklicznฤ… w kodzie.

W przypadku, gdy ustawienia sฤ… faล‚szywe, byฤ‡ moลผe nie bฤ™dziemy musieli uลผywaฤ‡ myExpensiveValue, co moลผe pomรณc nam uniknฤ…ฤ‡ wykonywania kosztownych obliczeล„, co pomaga zapewniฤ‡ uลผytkownikom dobrฤ… zabawฤ™ podczas korzystania z naszej aplikacji, poniewaลผ nasze inne potrzeby mogฤ… zostaฤ‡ poprawnie obliczone bez przytล‚aczania pamiฤ™ฤ‡ RAM.

W przypadku, gdy ustawienia sฤ… faล‚szywe, byฤ‡ moลผe nie bฤ™dziemy musieli uลผywaฤ‡ myExpensiveValue, co moลผe pomรณc nam uniknฤ…ฤ‡ wykonywania kosztownych obliczeล„, co pomaga zapewniฤ‡ uลผytkownikom dobrฤ… zabawฤ™ podczas korzystania z naszej aplikacji, poniewaลผ nasze inne potrzeby mogฤ… zostaฤ‡ odpowiednio obliczone bez przytล‚aczania pamiฤ™ฤ‡ RAM.

Lenistwo pomaga rรณwnieลผ w przypadku argumentรณw funkcji, gdzie argumenty sฤ… uลผywane tylko wtedy, gdy istnieje odwoล‚anie do nich wewnฤ…trz funkcji. Ta koncepcja nazywa siฤ™ parametrami Call-by-name.

def sometimesUsedString(someValue:String, defaultValue:=> String)={
 if(someValue != null){
   use(defaultValue)
 }else{
   use(someValue)
   }
 }

Wiele jฤ™zykรณw uลผywa metody call-by-value do oceny argumentรณw. Parametr przekazywany przez call-by-name bฤ™dzie oceniany tylko wtedy, gdy bฤ™dzie potrzebny w ciele funkcji i nie bฤ™dzie oceniany przedtem. Po ocenie wartoล›ci jest ona przechowywana i moลผe byฤ‡ ponownie uลผyta pรณลบniej bez koniecznoล›ci jej ponownej oceny. Koncepcja ta jest znana jako memoizacja.

Wpisz wnioskowanie

W Scali nie musisz deklarowaฤ‡ typรณw dla kaลผdej tworzonej zmiennej. Dzieje siฤ™ tak, poniewaลผ kompilator Scala moลผe wnioskowaฤ‡ o typach w oparciu o ocenฤ™ prawej strony. Dziฤ™ki temu Twรณj kod bฤ™dzie bardziej zwiฤ™zล‚y โ€“ uwalnia nas od pisania szablonรณw, w ktรณrych oczekiwany typ jest oczywisty

var first:String = "Hello, "
var second:String = "World"
var third = first + second
//the compile infers that third is of type String

Funkcja wyลผszego rzฤ™du

Funkcja wyลผszego rzฤ™du to funkcja, ktรณra moลผe przyjmowaฤ‡ funkcje jako argumenty i zwracaฤ‡ funkcjฤ™ jako typ zwracany. W Scali funkcje sฤ… uwaลผane za obywateli pierwszej kategorii. Korzystanie z tych funkcji w ten sposรณb pozwala nam na duลผฤ… elastycznoล›ฤ‡ w zakresie rodzaju programรณw, ktรณre moลผemy tworzyฤ‡. Moลผemy tworzyฤ‡ funkcje dynamicznie i dynamicznie przekazywaฤ‡ funkcjonalnoล›ฤ‡ innym funkcjom.

def doMathToInt(n:Int, myMathFunction:Int=>Int): Int ={
    myMathFunction(n)
}

W powyลผszej funkcji przekazujemy int oraz funkcjฤ™, ktรณra przyjmuje int i zwraca int. Moลผemy przekazaฤ‡ dowolnฤ… funkcjฤ™ tego podpisu. Przez sygnaturฤ™ rozumiemy wejล›cie i wyjล›cie funkcji. Sygnatura Int=>Int oznacza, ลผe โ€‹โ€‹funkcja przyjmuje Int jako dane wejล›ciowe i zwraca Int jako dane wyjล›ciowe.

Podpis ()=>Int oznacza, ลผe โ€‹โ€‹funkcja nie przyjmuje niczego na wejล›ciu i zwraca Int na wyjล›ciu. Przykล‚adem takiej funkcji moลผe byฤ‡ funkcja generujฤ…ca dla nas losowฤ… liczbฤ™ int.

def generateRandomInt()={
 return scala.util.Random.nextInt()
}

Powyลผsza funkcja posiada sygnaturฤ™ ()=>Int

Moลผemy mieฤ‡ funkcjฤ™, ktรณra ma sygnaturฤ™ scala ()=>Unit. Oznacza to, ลผe funkcje nie pobierajฤ… niczego i nie zwracajฤ… typu. Funkcja moลผe polegaฤ‡ na wykonywaniu pewnego rodzaju obliczeล„ poprzez zmianฤ™ czegoล› na wykonanie czegoล› z gรณry okreล›lonego.

Tego rodzaju metody nie sฤ… jednak mile widziane, poniewaลผ wydajฤ… siฤ™ byฤ‡ czarnฤ… skrzynkฤ…, ktรณra moลผe wpล‚ywaฤ‡ na system w nieznany sposรณb. Sฤ… rรณwnieลผ nietestowalne. Posiadanie jawnych typรณw danych wejล›ciowych i wyjล›ciowych pozwala nam wnioskowaฤ‡ o tym, co robi nasza funkcja.

Funkcja wyลผszego rzฤ™du moลผe rรณwnieลผ zwracaฤ‡ funkcjฤ™.

Na przykล‚ad moglibyล›my stworzyฤ‡ metodฤ™, ktรณra utworzy funkcjฤ™ potฤ™gujฤ…cฤ…, tj. pobierze liczbฤ™ i zastosuje do niej potฤ™gฤ™.

def powerByFunction(n:Int):Int=>Int = {
  return (x:Int)=> scala.math.pow(x,n).toInt
}

Powyลผsza funkcja przyjmuje liczbฤ™ typu int. Nasz typ zwracany to anonimowa funkcja, ktรณra przyjmuje Int x, * uลผywamy int x jako argumentu funkcji potฤ™gowej.

Curry

W Scali moลผemy przeksztaล‚ciฤ‡ funkcjฤ™ przyjmujฤ…cฤ… dwa argumenty w funkcjฤ™ przyjmujฤ…cฤ… po jednym argumencie. Kiedy przekazujemy jeden argument, czฤ™ล›ciowo go stosujemy i otrzymujemy funkcjฤ™, ktรณra do zakoล„czenia funkcji przyjmuje jeden argument. Curry umoลผliwia nam tworzenie funkcji poprzez czฤ™ล›ciowe dodanie niektรณrych argumentรณw.

Moลผe to byฤ‡ przydatne do dynamicznego tworzenia funkcji, zanim bฤ™dziemy mieli peล‚ny zestaw argumentรณw

def multiply two numbers(n:Int)(m:Int): Unit ={
  return n * m
}

Jeล›li musimy utworzyฤ‡ funkcjฤ™ mnoลผฤ…cฤ… przez okreล›lonฤ… liczbฤ™, nie musimy tworzyฤ‡ kolejnej metody mnoลผenia.

Moลผemy po prostu wywoล‚aฤ‡ funkcjฤ™ .curried w naszej funkcji powyลผej i uzyskaฤ‡ funkcjฤ™, ktรณra najpierw przyjmuje jeden argument i zwraca czฤ™ล›ciowo zastosowanฤ… funkcjฤ™

def multiplyTwoNumbers(n:Int)(m:Int): Unit ={
  return n * m
}

var multiplyByFive = multiplyTwoNumbers(5) 

multiplyByFive(4)

//returns 20

Dopasowywanie wzorcรณw

Scala ma wbudowany potฤ™ลผny mechanizm pomagajฤ…cy nam sprawdziฤ‡, czy zmienna speล‚nia okreล›lone kryteria, podobnie jak zrobilibyล›my to w instrukcji switch w Java lub w serii instrukcji if/else. Jฤ™zyk posiada funkcjฤ™ dopasowywania wzorcรณw, za pomocฤ… ktรณrej moลผemy sprawdziฤ‡, czy zmienna jest okreล›lonego typu. Dopasowywanie wzorcรณw w Scali jest potฤ™ลผne i moลผna go wykorzystaฤ‡ do zniszczenia komponentรณw wyposaลผonych w metodฤ™ unapply w celu uzyskania interesujฤ…cych nas pรณl bezpoล›rednio z dopasowywanej zmiennej.

Dopasowywanie wzorcรณw w Scali zapewnia rรณwnieลผ przyjemniejszฤ… skล‚adniฤ™ w porรณwnaniu z instrukcjฤ… switch.

myItem match {
  case true => //do something
  case false => //do something else
  case  _ => //if none of the above do this by default
}

Porรณwnujemy naszฤ… zmiennฤ… z zestawem opcji i kiedy dopasowywana zmienna speล‚nia kryteria, wyraลผenie po prawej stronie grubej strzaล‚ki (=>) jest oceniane i zwracane jako wynik dopasowania.

Uลผywamy podkreล›lenia, aby wychwyciฤ‡ przypadki, ktรณre nie sฤ… dopasowane w naszym kodzie. Odzwierciedla zachowanie domyล›lnego przypadku w przypadku instrukcji switch.

class Animal(var legs:Int,var sound:String)
class Furniture(var legs:Int, var color:Int, var woodType:String)

myItem match {
case myItem:Animal => //do something
case myItem:Furniture => //do something else
case _ => //case we have a type we don't recognize do sth else
}

W powyลผszym kodzie moลผesz znaleลบฤ‡ typ zmiennej myItem i na tej podstawie przejล›ฤ‡ do okreล›lonego kodu.

Dopasowanie wzorca sprawdza, czy zmienna pasuje

Podkreล›lenie dziaล‚a jako symbol zastฤ™pczy pasujฤ…cy do dowolnego innego warunku, ktรณry nie jest speล‚niony przez inne elementy w powyลผszych instrukcjach case. Bierzemy zmiennฤ… myItem i wywoล‚ujemy metodฤ™ dopasowania.

  • sprawdzamy, czy myItem jest prawdziwy, uลผywajฤ…c i wykonujฤ…c pewne czynnoล›ci logiczne po prawej stronie grubej strzaล‚ki โ€ž=>โ€.
  • uลผywamy podkreล›lenia, aby dopasowaฤ‡ wszystko, co nie pasuje do ลผadnej instrukcji case, ktรณrฤ… zdefiniowaliล›my w kodzie.

Dziฤ™ki klasom Case moลผemy nawet pรณjล›ฤ‡ dalej i zniszczyฤ‡ klasฤ™, aby uzyskaฤ‡ pola wewnฤ…trz obiektu.

Uลผywajฤ…c sล‚owa kluczowego seal do definiowania naszych klas, uzyskujemy korzyล›ฤ‡ polegajฤ…cฤ… na tym, ลผe kompilator dokล‚adnie sprawdza przypadki, z ktรณrymi staramy siฤ™ dopasowaฤ‡, i ostrzega nas, jeล›li zapomnimy zajฤ…ฤ‡ siฤ™ konkretnym.

Niezmiennoล›ฤ‡

Za pomocฤ… sล‚owa kluczowego val moลผna tworzyฤ‡ wartoล›ci, ktรณrych nie mogฤ… zmieniaฤ‡ inne funkcje w Scali. Osiฤ…ga siฤ™ to w Java za pomocฤ… sล‚owa kluczowego final. W Scali robimy to, uลผywajฤ…c sล‚owa kluczowego val podczas tworzenia zmiennej, zamiast uลผywaฤ‡ var, czyli alternatywy, ktรณrej uลผylibyล›my do utworzenia zmiennej modyfikowalnej.

Zmienna zdefiniowana za pomocฤ… sล‚owa kluczowego val jest tylko do odczytu, natomiast zmienna zdefiniowana za pomocฤ… var moลผe zostaฤ‡ odczytana i zmieniona przez inne funkcje lub dowolnie przez uลผytkownika w kodzie.

var changeableVariable = 8

changeableVariable =10
//the compiler doesn't complain, and the code compiles successfully

println(changeableVariable)
//10

val myNumber = 7

myNumber = 4

//if we try this the code won't compile

Prรณba przypisania wartoล›ci do myNumber po zadeklarowaniu jej jako wartoล›ci val powoduje bล‚ฤ…d kompilacji lub โ€žponowne przypisanie do wartoล›ci valโ€.

Po co uลผywaฤ‡ niezmiennoล›ci?

Niezmiennoล›ฤ‡ pomaga nam zapobiegaฤ‡ nieoczekiwanym zmianom naszych wartoล›ci przez kod i innych programistรณw, co mogล‚oby prowadziฤ‡ do nieoczekiwanych wynikรณw, jeล›li zamiast tego majฤ… uลผywaฤ‡ przechowywanej przez nas wartoล›ci, mogฤ… zamiast tego utworzyฤ‡ jej kopiฤ™. W ten sposรณb zapobiega siฤ™ bล‚ฤ™dom, ktรณre mogฤ… byฤ‡ spowodowane przez wielu aktorรณw zmieniajฤ…cych tฤ™ samฤ… zmiennฤ….

Klasy i przedmioty

Wszyscy wiemy, ลผe obiekty to byty ล›wiata rzeczywistego, a klasa to szablon definiujฤ…cy obiekty. Klasy majฤ… zarรณwno stan, jak i zachowania. Stany sฤ… albo wartoล›ciami, albo zmiennymi. Zachowania sฤ… metodami w Scali.

Przyjrzyjmy siฤ™, jak zdefiniowaฤ‡ klasฤ™, utworzyฤ‡ jej instancjฤ™ i uลผywaฤ‡ jej w jฤ™zyku Scala.

Tutaj klasa o nazwie Rectangle, ktรณra ma dwie zmienne i dwie funkcje. Moลผesz takลผe uลผyฤ‡ parametrรณw lib bezpoล›rednio jako pรณl w programie. Masz obiekt, ktรณry ma metodฤ™ gล‚รณwnฤ… i utworzyล‚ instancjฤ™ klasy z dwiema wartoล›ciami.

Przykล‚ad:

class Rectangle( l: Int,  b: Int) {
  val length: Int = l
  val breadth: Int = b
  def getArea: Int = l * b
  override def toString = s"This is rectangle with length as $length and breadth as  $breadth"
  }
object RectObject {
  def main(args: Array[String]) {
    val rect = new Rectangle(4, 5)
    println(rect.toString)
    println(rect.getArea)    
  }
}

Wszystkie pola i metody sฤ… domyล›lnie publiczne w Scali. Konieczne jest uลผycie override, poniewaลผ metoda toString jest zdefiniowana dla obiektu w Scali.

Dziedzictwo

W jฤ™zyku Scala wystฤ™puje wiele typรณw dziedziczenia (takich jak dziedziczenie pojedyncze, wielopoziomowe, wielokrotne, hierarchiczne i hybrydowe), ktรณre majฤ… wiele wspรณlnego z tradycyjnymi formami wystฤ™pujฤ…cymi w Java. Moลผna dziedziczyฤ‡ zarรณwno z klas, jak i cech. Moลผesz dziedziczyฤ‡ elementy jednej klasy do innej klasy, uลผywajฤ…c sล‚owa kluczowego โ€žrozszerzaโ€. Umoลผliwia to ponowne uลผycie.

Moลผliwe jest dziedziczenie z jednej klasy lub wielu klas. Moลผliwe jest takลผe dziedziczenie z podklas, ktรณre same majฤ… swoje nadklasy, tworzฤ…c przy tym hierarchiฤ™ dziedziczenia.

W poniลผszym przykล‚adzie w Scali klasฤ… bazowฤ… jest Circle, a klasฤ… pochodnฤ… jest Sphere. Okrฤ…g ma wartoล›ฤ‡ zwanฤ… promieniem, ktรณra jest dziedziczona w klasie Sphere. Metoda calcArea jest zastฤ™powana przy uลผyciu sล‚owa kluczowego override.

Przykล‚ad:

class Circle {
  val radius = 5;
  def calcArea = {
    println(radius * radius )
  }
}
class Sphere extends Circle{
 override def calcArea = {
    println(radius * radius * radius )
  }
}
  object SphereObject{
    def main(args : Array[String]){
      new Sphere().calcArea 
    }
  }

Abstrakcja

W Scali moลผemy tworzyฤ‡ abstrakcyjne metody i pola skล‚adowe, korzystajฤ…c z abstrakcyjnych klas i cech. Wewnฤ…trz abstrakcyjnych klas i cech moลผemy definiowaฤ‡ abstrakcyjne pola bez koniecznoล›ci ich implementowania.

Przykล‚ad:

trait MakesSound{
    var nameOfSound:String
    def sound():String
}
abstract class HasLegs(var legs:Int){
    val creatureName:String

    def printLegs():String={
        return s"$creatureName has this number of legs: $legs"
    }
}

Te pola sฤ… implementowane przez klasy rozszerzajฤ…ce cechฤ™ lub klasฤ™ abstrakcyjnฤ…. Moลผesz uลผyฤ‡ cech, aby tworzyฤ‡ kontrakty dotyczฤ…ce tego, co nasza aplikacja powinna byฤ‡ w stanie zrobiฤ‡, a nastฤ™pnie implementowaฤ‡ te metody pรณลบniej.

trait DatabaseService{
    def addItemName(itemName:String)
    def removeItem(itemId:Int)
    def updateItem(itemId:Int, newItemName:String)
}

W ten sposรณb moลผemy zaplanowaฤ‡, jak bฤ™dzie wyglฤ…daฤ‡ nasza aplikacja, bez koniecznoล›ci wdraลผania metod, ktรณre pomogฤ… nam wyobraziฤ‡ sobie, jak bฤ™dฤ… wyglฤ…daฤ‡ rรณลผne metody. Wynika to ze wzorca znanego jako programowanie abstrakcji, a nie faktyczna implementacja.

Klasa poprzedzona sล‚owem kluczowym streszczenie moลผe zawieraฤ‡ zarรณwno metody abstrakcyjne, jak i nieabstrakcyjne. Jednak wielokrotne dziedziczenie nie jest obsล‚ugiwane w klasie abstrakcyjnej. Moลผna wiฤ™c rozszerzyฤ‡ maksymalnie jednฤ… klasฤ™ abstrakcyjnฤ….

Obiekty Singletona

Singleton to klasa, ktรณrej instancja jest tworzona tylko raz w programie. Pochodzi z popularnego i uลผytecznego wzorca programowania znanego jako โ€žwzorzec singletonowyโ€. Jest to przydatne przy tworzeniu instancji, ktรณre majฤ… byฤ‡ dล‚ugotrwaล‚e i bฤ™dฤ… powszechnie dostฤ™pne w caล‚ym programie, a ktรณrych stan jest integralnฤ… czฤ™ล›ciฤ… koordynowania zdarzeล„ w systemie. Tworzenie takiej klasy w Scali jest ล‚atwe, poniewaลผ Scala zapewnia nam prosty sposรณb tworzenia singletonรณw za pomocฤ… sล‚owa kluczowego object.

object UserProfile{
    var userName=""
    var isLoggedIn:Boolean = false
}

Moลผemy nastฤ™pnie odwoล‚ywaฤ‡ siฤ™ do tego obiektu w caล‚ym programie, majฤ…c gwarancjฤ™, ลผe wszystkie czฤ™ล›ci naszego programu zobaczฤ… te same dane, poniewaลผ istnieje tylko jedna jego instancja.

def getLoggedInStatus():Boolean={
   return UserProfile.isLoggedIn
}

def changeLoggedInStatus():Boolean={
    UserProfile.isLoggedIn = !UserProfile.isLoggedIn
    return  UserProfile.isLoggedIn
}

W Scali nie ma koncepcji elementรณw statycznych, dlatego naleลผy uลผywaฤ‡ obiektรณw singletonowych, ktรณre zachowujฤ… siฤ™ jak statyczne elementy klasy.

Klasy niejawne

Klasy niejawne to nowa funkcjonalnoล›ฤ‡ dodana po wersji 2.1. Jej gล‚รณwnym zadaniem jest dodanie nowej funkcjonalnoล›ci do klas zamkniฤ™tych.

Niejawne sล‚owo kluczowe powinno byฤ‡ zdefiniowane w klasie, obiekcie lub cesze. Gล‚รณwny konstruktor klasy ukrytej powinien mieฤ‡ dokล‚adnie jeden argument na swojej pierwszej liล›cie parametrรณw. Moลผe rรณwnieลผ zawieraฤ‡ dodatkowฤ… niejawnฤ… listฤ™ parametrรณw.

W poniลผszym przykล‚adzie Scala dodano nowฤ… funkcjฤ™ zastฤ™powania samogล‚osek ciฤ…gu znakรณw *.

object StringUtil {
  implicit class StringEnhancer(str: String) {
    
    def replaceVowelWithStar: String = str.replaceAll("[aeiou]", "*")
  }
}

Musisz zaimportowaฤ‡ w klasie, w ktรณrej go uลผywasz.

import StringUtil.StringEnhancer

object ImplicitEx extends App {
  val msg = "This is Guru99!"
  println(msg.replaceVowelWithStar)
}

Programowanie obiektowe (OOP) a programowanie funkcjonalne (FP)

W programach OOP konstruuje siฤ™ je poprzez grupowanie danych i funkcji, ktรณre operujฤ… na tych danych, w wysoce poล‚ฤ…czone jednostki. Obiekty przenoszฤ… swoje dane w polach i metodach, ktรณre na nich operujฤ…. W tym stylu programowania gล‚รณwnฤ… abstrakcjฤ… sฤ… dane, poniewaลผ tworzone metody majฤ… operowaฤ‡ na danych.

Programowanie funkcjonalne, z drugiej strony, oddziela dane i funkcje, ktรณre na nich operujฤ…. Dziฤ™ki temu programiล›ci mogฤ… traktowaฤ‡ funkcje jako abstrakcjฤ™ i siล‚ฤ™ napฤ™dowฤ… podczas modelowania programรณw.

Scala umoลผliwia programowanie funkcyjne poprzez traktowanie funkcji jako obywateli pierwszej klasy, co pozwala na przekazywanie ich jako wartoล›ci do innych funkcji i zwracanie ich rรณwnieลผ jako wartoล›ci. Poล‚ฤ…czenie tych dwรณch paradygmatรณw uczyniล‚o Scalฤ™ doskonaล‚ym wyborem do tworzenia zล‚oลผonego oprogramowania w rรณลผnych branลผach, takich jak Data Science.

Waลผne frameworki w Scali

Oto kilka waลผnych frameworkรณw Scali

  • Graj to platforma aplikacji internetowych o otwartym kodzie ลบrรณdล‚owym, ktรณra wykorzystuje Architektura MVC. Wydany w 2007 roku i obecnie licencjonowany na platformie Apache, staล‚ siฤ™ najpopularniejszym frameworkiem w GitHub w 2013 roku. Firmy takie jak LinkedIn, Walmart, Samsung, Eero korzystajฤ… z tego frameworka.
  • Wyciฤ…g to kolejny darmowy framework sieciowy napisany w Scali, uruchomiony w 2007 roku. Foursquare wykorzystuje framework Lift. Jest wydajny i szybszy w budowie.
  • Jak
  • koty
  • Spark

Wsparcie wspรณล‚bieลผnoล›ci

  • Wartoล›ci w Scali sฤ… domyล›lnie niezmienne. To sprawia, ลผe โ€‹โ€‹bardzo dobrze dostosowuje siฤ™ do wspรณล‚bieลผnego ล›rodowiska.
  • W Scali jest wiele funkcji, ktรณre sprawiajฤ…, ลผe najlepiej sprawdza siฤ™ w przypadku aplikacji wspรณล‚bieลผnych.
  • Futures i Promises uล‚atwiajฤ… asynchroniczne przetwarzanie danych, wspierajฤ…c w ten sposรณb paralelizm.
  • Akka โ€“ narzฤ™dzie wykorzystujฤ…ce model wspรณล‚bieลผnoล›ci Actor. Istnieje pewna liczba aktorรณw, ktรณrzy podejmujฤ… dziaล‚ania po otrzymaniu wiadomoล›ci.
  • Wspรณล‚bieลผnoล›ฤ‡ przy uลผyciu wฤ…tkรณw z Java moลผe byฤ‡ rรณwnieลผ obsล‚ugiwany w Scali.
  • Przetwarzanie strumieniowe to kolejna ล›wietna funkcja, ktรณra umoลผliwia ciฤ…gล‚e przetwarzanie danych w czasie rzeczywistym.

Scala ma jedne z najlepszych bibliotek wspรณล‚bieลผnoล›ci na rynku Java ekosystem.

  • Tubylec Java threads
  • Wล‚รณkna z bibliotek takich jak Vertex
  • ZIO โ€“ biblioteka zawierajฤ…ca prymitywy uล‚atwiajฤ…ce radzenie sobie z obliczeniami wspรณล‚bieลผnymi i asynchronicznymi
  • STM โ€“ transakcja
  • Future โ€“ wbudowany w jฤ™zyk Scala

Java kontra Scala

Oto gล‚รณwne rรณลผnica miฤ™dzy Java i Scalฤ™.

Scala Java
Bardziej zwarty i zwiฤ™zล‚y Stosunkowo wiฤ™ksze fragmenty kodu
Zaprojektowany i opracowany jako jฤ™zyk zorientowany obiektowo i funkcjonalnie.
Obsล‚uguje szerokฤ… gamฤ™ funkcjonalnych funkcji programowania, takich jak wspรณล‚bieลผnoล›ฤ‡, niezmiennoล›ฤ‡.
Pierwotnie rozwijany jako jฤ™zyk obiektowy i zaczฤ…ล‚ obsล‚ugiwaฤ‡ funkcje programowania funkcyjnego w ostatnich dniach. Nadal nie jest silny jako jฤ™zyk programowania funkcyjnego.
Wykorzystuje model aktora do obsล‚ugi wspรณล‚bieลผnoล›ci, ktรณry jest nowoczesny Uลผywa konwencjonalnego modelu opartego na wฤ…tkach do wspรณล‚bieลผnoล›ci.
Obsล‚uguje frameworki โ€“ Play, Lift Obsล‚uguje Spring, Grails i wiele wiฤ™cej
Obsล‚uguje leniwฤ… ocenฤ™ Nie obsล‚uguje leniwej oceny
Brak elementรณw statycznych Zawiera elementy statyczne
Obsล‚uguje przeciฤ…ลผanie operatora Nie obsล‚uguje przeciฤ…ลผania operatora
Kompilacja kodu ลบrรณdล‚owego jest stosunkowo powolna Kompilacja kodu ลบrรณdล‚owego jest szybsza niลผ w Scali
Cechy โ€“ zachowuj siฤ™ jak Java 8 interfejsy Java 8 interfejsรณw prรณbuje wypeล‚niฤ‡ lukฤ™ pomiฤ™dzy klasami i interfejsami
Konieczne jest przepisanie Przepisywanie nie jest wymagane
Brak gwarancji, ลผe kody sฤ… wolne od bล‚ฤ™dรณw Peล‚na gwarancja mniejszych usterek
Obsล‚uguje kompatybilnoล›ฤ‡ wstecznฤ…. Scala nie obsล‚uguje kompatybilnoล›ci wstecznej.
Operatory sฤ… traktowane inaczej Java i nie sฤ… wywoล‚aniami metod. Wszyscy operatorzy na wpisach korzystajฤ… z metody wywoล‚ywanej w Scali.
Obsล‚uguje wielokrotne dziedziczenie przy uลผyciu klas, ale nie klas abstrakcyjnych Nie obsล‚uguje wielokrotnego dziedziczenia przy uลผyciu klas, ale przez interfejsy
Kod jest napisany w zwartej formie. Kod jest napisany w dล‚ugiej formie.
Scala nie zawiera sล‚owa kluczowego static. Java zawiera sล‚owo kluczowe static.

Podsumowanie

W tym samouczku nauczyล‚eล› siฤ™, jak rozpoczฤ…ฤ‡ pracฤ™ ze Scalฤ…. Poznaล‚eล› takลผe cechy funkcjonalne i obiektowe. Odkryล‚eล› takลผe podobieล„stwa i rรณลผnice miฤ™dzy nimi Java i Scalฤ™. Ten samouczek powinien byล‚ ci pomรณc dziฤ™ki szerokiej gamie dobrze zademonstrowanych przykล‚adรณw.

Podsumuj ten post nastฤ™pujฤ…co: