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.
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.
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.
Krok 2) Uruchom instalacjฤ
Po pobraniu programu IntelliJ kliknij go dwukrotnie, aby uruchomiฤ kreatora instalacji, i postฤpuj zgodnie z instrukcjami.
Krok 3) Wybierz lokalizacjฤ
Wybierz lokalizacjฤ, w ktรณrej chcesz zainstalowaฤ IDE.
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.
Krok 4) Kliknij dalej
Pozostaw pozostaลe ustawienia domyลlne bez zmian i kliknij Dalej.
Krok 5) Kliknij ikonฤ uruchamiania
Po zakoลczeniu instalacji uruchom IntelliJ IDE, klikajฤ
c jego ikonฤ uruchamiania w menu startowym, jak zwykลฤ
aplikacjฤ.
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.
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.
Krok 7) Uruchom ponownie IDE
Po zakoลczeniu pobierania zostaniesz poproszony o ponowne uruchomienie IDE, aby zainstalowana wtyczka mogลa zaczฤ
ฤ dziaลaฤ.
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.
Krok 2) wybierz Scalฤ zaznaczajฤ c pole wyboru Scala i kliknij Dalej.
Krok 3) Wybierz lokalizacjฤ, w ktรณrej chcesz zapisaฤ plik naszego projektu i nadaj naszemu projektowi nazwฤ.
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.
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.
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โ
Gdy to zrobimy, bฤdziemy mieli plik Scala zawierajฤ cy obiekt Singleton, ktรณrego uลผyjemy do uruchomienia naszego kodu.
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.
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.
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.






















