Poradnik Scali
โก Inteligentne podsumowanie
Scala Tutorial wprowadza statycznie typowany jฤzyk oparty na JVM, ktรณry ลฤ czy programowanie obiektowe i funkcyjne. Przewodnik obejmuje instalacjฤ, skลadniฤ, podstawowe funkcje i frameworki, ktรณre sprawiajฤ , ลผe Scala idealnie nadaje siฤ do tworzenia wspรณลbieลผnych, skalowalnych i zwiฤzลych, nowoczesnych aplikacji.

Czym jest Scala?
Scala to statycznie typowany jฤzyk programowania, ktรณry ลฤ czy programowanie obiektowe i funkcyjne w celu poprawy skalowalnoลci aplikacji. Scala dziaลa gลรณwnie na platformie JVM, a programiลci mogฤ jej rรณwnieลผ uลผywaฤ do pisania oprogramowania na platformy natywne za poลrednictwem Scala-Native lub na przeglฤ darki za poลrednictwem ScalaJS iโฆ JAVASCRIPT czas wykonywania.
Scala to skalowalny jฤzyk uลผywany do tworzenia oprogramowania na wiele platform, od ktรณrego wziฤลa siฤ jego nazwa. Jฤzyk ten zostaล zaprojektowany, aby rozwiฤ zaฤ kilka problemรณw zwiฤ zanych z โrozwlekลoลciฤ โ wโฆ Java zachowujฤ c jednoczeลnie zwiฤzลoลฤ. Martin Odersky zaprojektowaล Scalฤ, a jej pierwsza publiczna wersja ukazaลa siฤ w 2004 roku.
Dlaczego warto uczyฤ siฤ Scali
Oto najwaลผniejsze powody, dla ktรณrych warto nauczyฤ siฤ jฤzyka programowania Scala:
- Scala jest ลatwa do nauczenia dla programistรณw obiektowych i Java programistรณw i staล siฤ jednym z popularnych jฤzykรณw w ostatnich latach.
- Scala oferuje uลผytkownikom najwyลผszej klasy funkcje.
- Scalฤ moลผna wykonaฤ na FMV, torujฤ c drogฤ do interoperacyjnoลci z innymi jฤzykami.
- Jest on przeznaczony do aplikacji wspรณลbieลผnych, rozproszonych i odpornych na bลฤdy, sterowanych komunikatami, co czyni go jednym z najbardziej poลผฤ danych jฤzykรณw tej dekady.
- Jest to zwiฤzลy i potฤลผny jฤzyk, ktรณry moลผe szybko rozwijaฤ siฤ w zaleลผnoลci od potrzeb uลผytkownikรณw.
- Jest zorientowany obiektowo i zawiera wiele funkcji programowania funkcyjnego, dajฤ c programistom duลผฤ swobodฤ w pisaniu kodu.
- Scala oferuje Duck Typing poprzez typy strukturalne.
- Zawiera mniej szablonรณw niลผ Java.
- Frameworki Lift i Play, napisane w jฤzyku Scala, stale siฤ rozwijajฤ i zyskujฤ na popularnoลci.
Jak zainstalowaฤ Scalฤ
Aby rozpoczฤ ฤ pisanie programรณw w Scali, musisz jฤ zainstalowaฤ na swoim komputerze. Aby to zrobiฤ, odwiedลบ oficjalnฤ stronฤ: https://www.scala-lang.org/download/ aby pobraฤ najnowszฤ wersjฤ jฤzyka Scala.
Po klikniฤciu linku zobaczysz dwie opcje instalacji Scali. W tym samouczku Scali uลผyjemy IntelliJ IDEA, ktรณry od razu po zainstalowaniu zapewnia doskonaลe wsparcie jฤzyka Scala.
Po klikniฤciu ลฤ cza pobierania znajdziesz dwie edycje ลrodowiska IDE IntelliJ.
Na potrzeby tego samouczka dotyczฤ cego jฤzyka Scala pobierzemy wersjฤ Community Edition, ktรณra jest bezpลatna i zawiera wszystko, czego potrzebujesz do pisania programรณw w jฤzyku Scala.
Krok 1) Wybierz wersjฤ Community Edition.
Na stronie kliknij menu rozwijane Community Edition.
Zawiera opcjฤ pobrania ลrodowiska IntelliJ IDE wraz z JBR, ktรณre zawiera implementacjฤ JDK (Java Zestaw narzฤdzi programistycznych (Development Kit), taki jak OpenJDK, ktรณrego jฤzyk Scala potrzebuje do kompilowania i uruchamiania kodu.
Krok 2) Uruchom instalacjฤ.
Po pobraniu IntelliJ kliknij dwukrotnie instalator i postฤpuj zgodnie z instrukcjami kreatora wyลwietlanymi na ekranie.
Krok 3) Wybierz lokalizacjฤ.
Wybierz lokalizacjฤ, w ktรณrej chcesz zainstalowaฤ IDE.
Jeลli nie pobrano pakietu z JDK, instalator i tak poprosi o dodanie JDK za pomocฤ pola wyboru podczas konfiguracji.
Krok 4) Kliknij Nastฤpny.
Pozostaลe ustawienia domyลlne pozostaw bez zmian i kliknij Dalej.
Program Scala Hello World
Krok 5) Kliknij ikonฤ uruchamiania.
Po zakoลczeniu instalacji uruchom ลrodowisko IntelliJ IDE, klikajฤ
c jego ikonฤ startowฤ
w menu Start, tak jak zwykลฤ
aplikacjฤ.
Nadal musisz dodaฤ wtyczkฤ Scala do IntelliJ. Kliknij menu rozwijane w menu konfiguracji w prawym dolnym rogu ekranu i wybierz opcjฤ โWtyczkiโ.
Na karcie Marketplace wyszukaj Scala. Wtyczka pojawi siฤ jako pierwszy wynik pod etykietฤ Jฤzyki.
Krok 6) Zainstaluj wtyczkฤ.
Kliknij Zainstaluj, aby rozpoczฤ
ฤ pobieranie wtyczki Scala.
Krok 7) Uruchom ponownie ลrodowisko IDE.
Po zakoลczeniu pobierania zostaniesz poproszony o ponowne uruchomienie IDE, aby zainstalowana wtyczka mogลa zaczฤ
ฤ dziaลaฤ.
Po ponownym uruchomieniu wrรณcisz do tej samej strony, ale tym razem wtyczka Scala bฤdzie zainstalowana i gotowa.
Krok 8) Wybierz opcjฤ Utwรณrz projekt, ktรณra przeniesie Ciฤ na stronฤ, na ktรณrej moลผesz wybraฤ jฤzyk projektu.
Krok 9) Wybierz Scalฤ, zaznaczajฤ c pole wyboru Scala i klikajฤ c Dalej.
Krok 10) Wybierz lokalizacjฤ, w ktรณrej chcesz zapisaฤ plik projektu i nadaj mu nazwฤ.
Jeลli katalog nie istnieje, IntelliJ poprosi o pozwolenie na utworzenie folderu. Zaakceptuj i kliknij Zakoลcz. Nastฤpnie zostaniesz przeniesiony do swojego projektu Scala, ktรณry obecnie nie zawiera ลผadnego kodu Scala.
ลadowanie indeksรณw zajmuje trochฤ czasu, wiฤc nie martw siฤ, jeลli nie moลผesz korzystaฤ ze ลrodowiska IDE, gdy na dole wyลwietla siฤ pasek postฤpu. IDE ลaduje pliki wymagane do uruchomienia jฤzyka Scala i zapewnia funkcjฤ autouzupeลniania.
Krok 11) Kliknij kartฤ Projekt po lewej stronie ลrodowiska IDE i rozwiล jฤ , aby zobaczyฤ zawartoลฤ projektu.
Na tym etapie projekt jest pusty i zawiera jedynie folder .idea oraz plik hello-world.iml wygenerowany przez IDE. Interesujฤ cy jest folder src, w ktรณrym znajduje siฤ kod ลบrรณdลowy projektu. To wลaลnie tam tworzysz swรณj pierwszy plik Scala.
Krok 12) Kliknij prawym przyciskiem myszy na src, aby otworzyฤ menu i utworzyฤ nowy plik Scala.
Wybierz nazwฤ pliku. W tym samouczku dotyczฤ cym jฤzyka Scala uลผyj czeลฤ, a nastฤpnie wybierz Obiekt z listy rozwijanej, aby okreลliฤ typ zawartoลci pliku Scala.
Po wykonaniu tej czynnoลci otrzymasz plik Scala zawierajฤ cy obiekt singleton, ktรณrego bฤdziesz uลผywaฤ do uruchamiania kodu.
Majฤ c juลผ plik Scala zawierajฤ cy obiekt Hello, moลผesz napisaฤ swรณj pierwszy program, rozszerzajฤ c obiekt utworzony za pomocฤ sลowa kluczowego App.
Rozszerzenie obiektu o App informuje kompilator, ktรณry kod ma zostaฤ uruchomiony podczas startu programu. Zaraz po rozszerzeniu App po lewej stronie pojawia siฤ zielona strzaลka, wskazujฤ ca, ลผe โโprogram jest teraz gotowy do uruchomienia.
W obiekcie Hello wpisz funkcjฤ println(), aby wydrukowaฤ tekst na konsoli. Uruchom program, klikajฤ c zielonฤ strzaลkฤ.
Klikniฤcie strzaลki wyลwietla opcjฤ โUruchom Helloโ. Wybranie jej powoduje kompilacjฤ kodu, a po kilku sekundach w konsoli IntelliJ pojawi siฤ wynik dziaลania programu.
Pomyลlnie zainstalowaลeล Scalฤ i uruchomiลeล swรณj pierwszy program.
Co moลผesz zrobiฤ ze Scalฤ
Scala jest szeroko stosowana w wielu dziedzinach ze wzglฤdu na swojฤ elastycznoลฤ i interoperacyjnoลฤ z JVM. Typowe zastosowania obejmujฤ :
- Tworzenie front-endu stron internetowych w ScalaJS.
- Rozwรณj mobilny dla Android i iOS z natywnฤ obsลugฤ Scala.
- Biblioteki po stronie serwera, takie jak HTTP4S, Akka-Http i Play Framework.
- Zastosowania Internetu Rzeczy (IoT).
- Produkcja gier.
- Przetwarzanie jฤzyka naturalnego z wykorzystaniem pakietu bibliotek ScalaNLP.
- Wspรณlne ฤwiczenie zaawansowanych technik, takich jak programowanie funkcyjne i programowanie obiektowe.
- Wysoce wspรณลbieลผne aplikacje komunikacyjne wykorzystujฤ ce aktorรณw, bibliotekฤ dla JVM inspirowanฤ Erlangiem.
- Uczenie maszynowe z bibliotekami takimi jak Figaro do programowania probabilistycznego i Apache Spark do przetwarzania danych na duลผฤ skalฤ.
Funkcje anonimowe
Jฤzyk Scala obsลuguje funkcje anonimowe, zwane takลผe literaลy funkcyjnePoniewaลผ Scala jest jฤzykiem funkcyjnym, programiลci czฤsto dzielฤ
duลผe problemy na wiele maลych zadaล i tworzฤ
wiele funkcji. Aby to uลatwiฤ, Scala pozwala na tworzenie funkcji utworzone bez nazwyMoลผesz je przypisaฤ bezpoลrednio do zmiennych lub definicji za pomocฤ
def, jak pokazano w poniลผszym przykลadzie Scala:
val multiplyByTwo = (n:Int) => n * 2 def multiplyByThree = (n:Int) => n * 3
Nastฤpnie moลผna ich uลผywaฤ jak zwykลych funkcji, przekazujฤ c parametry:
multiplyByTwo(3) //6 multiplyByThree(4) //12
Te metody sฤ przydatne, gdy zaleลผy Ci na przejrzystym i zwiฤzลym kodzie. Funkcje anonimowe sฤ przydatne przy definiowaniu metod, ktรณre sฤ maลe i nie wymagajฤ duลผej iloลci kodu w swoim ciele. Sฤ bardzo proste i nie wymagajฤ ลผadnych formalnoลci przy tworzeniu.
Metody te nie ograniczajฤ siฤ wyลฤ cznie 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 kodu, w ktรณrych potrzebna jest szybka funkcja. Z tego powodu nazywa siฤ je rรณwnieลผ funkcje wbudowaneKorzystanie z funkcji anonimowych to powszechny wzorzec pojawiajฤ cy siฤ w caลej bibliotece kolekcji w celu wykonywania szybkich akcji na kolekcji.
Na przykลad metoda filter przyjmuje funkcjฤ inline w celu utworzenia innej kolekcji zawierajฤ cej wyลฤ cznie elementy speลniajฤ ce kryteria zdefiniowane 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)
W tym przypadku funkcje anonimowe sprawdzajฤ , czy wartoลฤ na liลcie jest parzysta czy nieparzysta i zwracajฤ pasujฤ cy 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ลผliwe jest rรณwnieลผ uลผycie symboli wieloznacznych, gdy parametr funkcji anonimowej nie jest nazwany. Na przykลad:
var timesTwo = (_:Int) * 2 timesTwo(5) //10
W tym scenariuszu nie nadajesz parametrowi nazwy. Do jego reprezentacji uลผywa siฤ znaku podkreลlenia.
Leniwa ocena
Wiฤkszoลฤ jฤzykรณw ocenia zmienne i parametry funkcji sekwencyjnie, jeden po drugim. W Scali sลowo kluczowe lazy pomaga radziฤ sobie z wartoลciami, ktรณrych nie chcesz oceniaฤ, dopรณki siฤ do nich nie odwoลasz.
Zmienna oznaczona jako leniwa nie jest oceniana w miejscu, w ktรณrym zostaลa zdefiniowana, co jest powszechnie znane jako ocena zachลanna. Jest ona oceniana dopiero po odwoลaniu siฤ do niej w dalszej czฤลci kodu.
Moลผe to byฤ pomocne, gdy ocena wartoลci byลaby kosztownym obliczeniem. Jeลli wartoลฤ nie jest zawsze potrzebna, oszczฤdzasz sobie wykonywania kosztownych obliczeล, ktรณre mogลyby spowolniฤ dziaลanie oprogramowania, powodujฤ c, ลผe zmienna staลaby siฤ leniwa.
lazy val myExpensiveValue = expensiveComputation def runMethod() = { if(settings == true) { use(myExpensiveValue) } else { use(otherValue) } }
To nie jedyny przypadek zastosowania zmiennych โleniwychโ. Pomagajฤ one rรณwnieลผ radziฤ sobie z zaleลผnoลciami cyklicznymi w kodzie.
Jeลli flaga ustawieล ma wartoลฤ false, nie musisz uลผywaฤ myExpensiveValue, co pozwala uniknฤ ฤ kosztownych obliczeล. Pomaga to zapewniฤ uลผytkownikom pลynne dziaลanie, poniewaลผ zasoby nie sฤ marnowane na wartoลci, ktรณre nigdy nie sฤ odczytywane.
Lenistwo pomaga rรณwnieลผ w przypadku argumentรณw funkcji, gdzie argumenty sฤ uลผywane tylko wtedy, gdy odwoลujemy siฤ do nich wewnฤ trz funkcji. Ta koncepcja nazywa siฤ parametrami wywoลania przez nazwฤ.
def sometimesUsedString(someValue:String, defaultValue: => String) = { if(someValue != null) { use(defaultValue) } else { use(someValue) } }
Wiele jฤzykรณw programowania wykorzystuje podejลcie call-by-value do oceny argumentรณw. Parametr przekazywany przez call-by-name jest oceniany tylko wtedy, gdy jest potrzebny w ciele funkcji. Po ocenie wartoลฤ jest zapisywana i moลผe byฤ ponownie uลผyta bez koniecznoลci ponownej oceny โ koncepcja ta nazywa siฤ memoizacjฤ .
Wpisz wnioskowanie
W Scali nie trzeba deklarowaฤ typรณw dla kaลผdej tworzonej zmiennej, poniewaลผ kompilator Scali moลผe wnioskowaฤ typy z prawej strony wyraลผenia. Dziฤki temu kod jest bardziej zwiฤzลy i nie trzeba pisaฤ szablonowych kodรณw, w ktรณrych oczekiwany typ jest oczywisty.
var first:String = "Hello, " var second:String = "World" var third = first + second //the compiler 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ฤ traktowane jako obywatele pierwszej klasy. Korzystanie z funkcji w ten sposรณb zapewnia duลผฤ elastycznoลฤ w zakresie rodzajรณw tworzonych programรณw. Moลผna tworzyฤ funkcje dynamicznie i dynamicznie przekazywaฤ funkcjonalnoลฤ innym funkcjom.
def doMathToInt(n:Int, myMathFunction:Int=>Int): Int = { myMathFunction(n) }
W powyลผszej funkcji przekazujesz Int i funkcja, ktรณra przyjmuje Int i zwraca IntMoลผesz przekazaฤ dowolnฤ
funkcjฤ o tej sygnaturze. Przez sygnaturฤ rozumiemy dane wejลciowe i wyjลciowe funkcji. Sygnatura Int => Int oznacza, ลผe โโfunkcja przyjmuje wartoลฤ Int jako dane wejลciowe i zwraca wartoลฤ Int jako dane wyjลciowe.
Podpis () => Int Oznacza to, ลผe funkcja przyjmuje nic jako dane wejลciowe i zwraca wartoลฤ typu Int jako wynik. Przykลadem takiej funkcji jest funkcja generujฤ
ca losowฤ
wartoลฤ typu int.
def generateRandomInt() = { return scala.util.Random.nextInt() }
Powyลผsza funkcja ma sygnaturฤ () => Int.
Funkcja moลผe rรณwnieลผ mieฤ sygnaturฤ () => UnitOznacza to, ลผe funkcja nie przyjmuje ลผadnych danych i nie zwraca typu. Zamiast tego moลผe zmieniฤ jakiล stan lub wykonaฤ z gรณry okreลlonฤ
akcjฤ.
Tego typu metody nie sฤ zalecane, poniewaลผ mogฤ dziaลaฤ jak czarna skrzynka, wpลywajฤ c na system w nieznany sposรณb. Sฤ one rรณwnieลผ trudniejsze do przetestowania. Jawne okreลlenie typรณw danych wejลciowych i wyjลciowych pozwala na wnioskowanie o dziaลaniu funkcji.
Funkcja wyลผszego rzฤdu moลผe rรณwnieลผ zwracaฤ funkcjฤ. Na przykลad, moลผesz utworzyฤ metodฤ zwracajฤ cฤ funkcjฤ potฤgujฤ cฤ , czyli takฤ , ktรณra przyjmuje liczbฤ i stosuje do niej potฤgฤ.
def powerByFunction(n:Int): Int=>Int = { return (x:Int) => scala.math.pow(x,n).toInt }
Powyลผsza funkcja przyjmuje wartoลฤ typu Int. Jej typem zwracanym jest funkcja anonimowa przyjmujฤ
ca wartoลฤ typu Int. x i uลผywa go jako argumentu dla funkcji potฤgowej.
Curry
W Scali moลผna przeksztaลciฤ funkcjฤ przyjmujฤ cฤ dwa argumenty w funkcjฤ przyjmujฤ cฤ po jednym argumencie. Przekazujฤ c jeden argument, czฤลciowo go stosujesz, a na koลcu otrzymujesz funkcjฤ przyjmujฤ cฤ pozostaลy argument, aby zakoลczyฤ wywoลanie. Currying pozwala na tworzenie funkcji poprzez czฤลciowe dodawanie argumentรณw.
Jest to przydatne w przypadku dynamicznego tworzenia funkcji, zanim uzyskasz kompletny zestaw argumentรณw.
def multiplyTwoNumbers(n:Int)(m:Int): Int = { return n * m }
Jeลli potrzebujesz funkcji mnoลผฤ cej przez okreลlonฤ liczbฤ, nie musisz tworzyฤ kolejnej metody mnoลผenia. Moลผesz zastosowaฤ jeden argument do funkcji curry i ponownie wykorzystaฤ wynik:
def multiplyTwoNumbers(n:Int)(m:Int): Int = { return n * m } var multiplyByFive = multiplyTwoNumbers(5) _ multiplyByFive(4) //returns 20
Dopasowywanie wzorcรณw
Jฤzyk Scala ma wbudowany, potฤลผny mechanizm, ktรณry pomaga sprawdziฤ, czy zmienna speลnia okreลlone kryteria, podobnie jak instrukcja switch w Java lub ลaลcuch instrukcji if/else. Jฤzyk obsลuguje dopasowywanie wzorcรณw, ktรณrego moลผna uลผyฤ do sprawdzenia, czy zmienna jest okreลlonego typu. Dopasowywanie wzorcรณw w Scali jest potฤลผne i umoลผliwia destrukturyzacjฤ komponentรณw, ktรณre majฤ
unapply metoda umoลผliwiajฤ
ca pobranie interesujฤ
cych Ciฤ pรณl bezpoลrednio ze zmiennej podlegajฤ
cej dopasowaniu.
Dopasowywanie wzorcรณw w jฤzyku Scala charakteryzuje siฤ rรณwnieลผ przyjemniejszฤ skลadniฤ niลผ polecenie switch.
myItem match { case true => //do something case false => //do something else case _ => //if none of the above do this by default }
Porรณwnujesz zmiennฤ z zestawem opcji. Gdy zmienna speลnia kryteria, wyraลผenie po prawej stronie grubej strzaลki (=>) jest oceniane i zwracane jako wynik dopasowania.
Podkreลlenie wychwytuje przypadki, ktรณre nie zostaลy uwzglฤdnione w kodzie, odzwierciedlajฤ c zachowanie przypadku domyลlnego w 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 _ => //unknown type, do something else }
W powyลผszym kodzie moลผna wykryฤ typ myItem zmiennฤ
i na jej podstawie przejลฤ do konkretnego kodu.
Dopasowywanie wzorcรณw sprawdza, czy zmienna pasuje do kaลผdego przypadku w kolejnoลci.
Podkreลlenie dziaลa jako symbol zastฤpczy, ktรณry pasuje do kaลผdego warunku, ktรณrego nie pasujฤ
inne instrukcje case. Bierzesz zmiennฤ
myItem i zadzwoล do match Metoda.
- Sprawdลบ pogodฤ
myItemistruei uruchom logikฤ po prawej stronie grubej strzaลki โ=>โ. - Uลผyj podkreลlenia, aby dopasowaฤ wszystko, co nie pasuje do ลผadnego ze stwierdzeล case zdefiniowanych w kodzie.
Za pomocฤ klas przypadkรณw moลผna rozลoลผyฤ klasฤ na np.tracpola t wewnฤ trz obiektu.
Przy uลผyciu sealed sลowo kluczowe definiujฤ
ce klasy, dziฤki ktรณremu kompilator dokลadnie sprawdza przypadki, ktรณre prรณbujesz dopasowaฤ, i ostrzega Ciฤ, jeลli zapomnisz o obsลuลผeniu ktรณregoล z nich.
Niezmiennoลฤ
Moลผna tworzyฤ wartoลci, ktรณrych nie moลผna zmieniฤ za pomocฤ
innych funkcji w Scali, uลผywajฤ
c val sลowo kluczowe. Osiฤ
ga siฤ to w Java przy uลผyciu final sลowo kluczowe. W Scali uลผywasz val podczas tworzenia zmiennej zamiast var, ktรณra jest alternatywฤ
dla zmiennych zmiennych.
Zmienna zdefiniowana za pomocฤ
val Sลowo kluczowe jest tylko do odczytu, podczas gdy zdefiniowane za pomocฤ
var mogฤ
byฤ odczytane i zmienione pรณลบniej przez inne funkcje lub przez uลผytkownika w kodzie.
var changeableVariable = 8 changeableVariable = 10 //the compiler does not complain, and the code compiles successfully println(changeableVariable) //10 val myNumber = 7 myNumber = 4 //this will not compile
Prรณba przypisania wartoลci myNumber po ogลoszeniu tego jako val zgลasza bลฤ
d kompilacji: โreassignment to val.โ
Po co uลผywaฤ niezmiennoลci?
Niezmiennoลฤ pomaga zapobiegaฤ nieoczekiwanym zmianom wartoลci przez kod i innych programistรณw, co prowadziลoby do nieprzewidywalnych rezultatรณw. Jeลli odbiorcy wartoลci muszฤ jฤ zmieniฤ, mogฤ jฤ skopiowaฤ. W ten sposรณb zapobiega siฤ bลฤdom spowodowanym przez wielu aktorรณw zmieniajฤ cych tฤ samฤ zmiennฤ .
Klasy i przedmioty
Obiekty to byty ze ลwiata rzeczywistego, a klasa to szablon definiujฤ cy obiekty. Klasy majฤ zarรณwno stan, jak i zachowania. Stany to wartoลci lub zmienne. Zachowania to metody w Scali.
W nastฤpnej sekcji pokazano, jak zdefiniowaฤ klasฤ, utworzyฤ jej instancjฤ i uลผywaฤ jej w Scali.
Oto klasa o nazwie Rectangle, ktรณra ma dwie wartoลci i dwie funkcje. Moลผesz rรณwnieลผ uลผyฤ parametrรณw l oraz b bezpoลrednio jako pola w programie. Masz obiekt, ktรณry ma metodฤ gลรณwnฤ
i tworzy 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 a rectangle with length $length and breadth $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. Korzystanie z nich jest niezbฤdne. override bo toString jest juลผ zdefiniowany dla kaลผdego obiektu w Scali.
Dziedzictwo
W jฤzyku Scala dostฤpne sฤ
rรณลผne typy dziedziczenia (pojedyncze, wielopoziomowe, wielokrotne, hierarchiczne i hybrydowe), ktรณre majฤ
wiele wspรณlnego z tradycyjnymi formami wystฤpujฤ
cymi w JavaMoลผesz dziedziczyฤ zarรณwno po klasach, jak i cechach. Dziedziczysz elementy jednej klasy do innej klasy za pomocฤ
sลowa kluczowego extends. Dziฤki temu moลผliwe jest ponowne wykorzystanie.
Moลผliwe jest dziedziczenie po jednej lub wielu klasach. Moลผliwe jest rรณwnieลผ dziedziczenie po podklasach, ktรณre same majฤ swoje nadklasy, tworzฤ c w ten sposรณb hierarchiฤ dziedziczenia.
W poniลผszym przykลadzie Scali klasฤ
bazowฤ
jest Circle, a klasa pochodna to SphereOkrฤ
g ma wartoลฤ zwanฤ
promieniem, ktรณra jest dziedziczona w klasie Sphere. Metoda calcArea jest zastฤpowany za pomocฤ
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 } }
Abstraccja
W Scali moลผesz tworzyฤ abstracmetody t i pola czลonkowskie wykorzystujฤ ce abstracKlasy i cechy. Wewnฤ trz brzuchatracklasy i cechy, moลผesz zdefiniowaฤ abstracpola t bez ich implementacji.
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" } }
Pola te sฤ implementowane przez klasy rozszerzajฤ ce cechฤ lub abstracKlasa t. Moลผesz uลผyฤ cech, aby stworzyฤtracokreลlajฤ , co aplikacja powinna robiฤ, a nastฤpnie implementujฤ 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ลผesz zaplanowaฤ, jak bฤdzie wyglฤ daลa aplikacja, bez koniecznoลci implementowania metod, helping Wyobraลผasz sobie, jak bฤdฤ wyglฤ daฤ rรณลผne metody. Postฤpuje to zgodnie ze schematem znanym jako programowanie abs.tracraczej na dziaลaniach niลผ na faktycznym wdroลผeniu.
Klasa poprzedzona abstract Sลowo kluczowe moลผe zawieraฤ zarรณwno abstract i nie-abstracmetody t. Jednakลผe dziedziczenie wielokrotne nie jest obsลugiwane w abstraczajฤcia, dziฤki czemu moลผesz rozciฤ
gaฤ tylko jeden miฤsieล brzuchatracklasa t.
Obiekty Singletona
Singleton to klasa, ktรณrej instancja jest tworzona tylko raz w programie. Wywodzi siฤ z popularnego i uลผytecznego wzorca programistycznego znanego jako โwzorzec singletonโ. Jest on przydatny do tworzenia instancji, ktรณre majฤ
byฤ dลugotrwaลe i powszechnie dostฤpne w caลym programie, gdzie stan jest integralnฤ
czฤลciฤ
koordynacji zdarzeล w systemie. Utworzenie takiej klasy w Scali jest ลatwe, poniewaลผ Scala oferuje prosty sposรณb tworzenia singletonรณw za pomocฤ
object sลowo kluczowe.
object UserProfile { var userName = "" var isLoggedIn:Boolean = false }
Nastฤpnie moลผna odwoลywaฤ siฤ do tego obiektu w caลym programie, majฤ c pewnoลฤ, ลผe wszystkie czฤลci programu widzฤ te same dane, poniewaลผ istnieje tylko jedno jego wystฤ pienie.
def getLoggedInStatus():Boolean = { return UserProfile.isLoggedIn } def changeLoggedInStatus():Boolean = { UserProfile.isLoggedIn = !UserProfile.isLoggedIn return UserProfile.isLoggedIn }
W jฤzyku Scala nie istnieje koncepcja elementรณw statycznych, dlatego stosuje siฤ obiekty singleton, ktรณre zachowujฤ siฤ jak elementy statyczne klasy.
Klasy niejawne
Klasy niejawne to funkcja dodana w wersji 2.10. Sลuลผฤ gลรณwnie do dodawania nowej funkcjonalnoลci do istniejฤ cych klas zamkniฤtych.
implicit Sลowo kluczowe powinno byฤ zdefiniowane w klasie, obiekcie lub cesze. Gลรณwny konstruktor klasy niejawnej musi 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 Scali dodano nowฤ funkcjonalnoลฤ umoลผliwiajฤ cฤ zastฤpowanie samogลosek w ciฤ gu znakรณw *.
object StringUtil { implicit class StringEnhancer(str: String) { def replaceVowelWithStar: String = str.replaceAll("[aeiou]", "*") } }
Musisz zaimportowaฤ klasฤ niejawnฤ do klasy, w ktรณrej jej uลผywasz.
import StringUtil.StringEnhancer object ImplicitEx extends App { val msg = "This is Guru99!" println(msg.replaceVowelWithStar) }
Programowanie obiektowe (OOP) a programowanie funkcyjne (FP)
W programowaniu obiektowym programy sฤ konstruowane przez grupyping Dane i funkcje operujฤ ce na tych danych ลฤ czฤ siฤ w silnie poลฤ czone jednostki. Obiekty przechowujฤ swoje dane w polach, a metody na nich operujฤ . W tym stylu programowania gลรณwnytracPodstawฤ sฤ dane, poniewaลผ tworzone metody majฤ na celu operowanie na danych.
Programowanie funkcjonalneZ drugiej strony, oddziela dane i funkcje, ktรณre na nich operujฤ . Dziฤki temu programiลci mogฤ traktowaฤ funkcje jako abs.traccja i siลa napฤdowa przy modelowaniu programรณw.
Scala umoลผliwia programowanie funkcyjne, traktujฤ c funkcje jako obywateli pierwszej klasy, umoลผliwiajฤ c ich przekazywanie jako wartoลci do innych funkcji i zwracanie ich rรณwnieลผ jako wartoลci. Poลฤ czenie tych dwรณch paradygmatรณw sprawiลo, ลผe Scala jest doskonaลym wyborem do tworzenia zลoลผonego oprogramowania w branลผach takich jak nauka o danych.
Waลผne frameworki w Scali
Oto kilka waลผnych struktur dla jฤzyka Scala:
- Graj to platforma aplikacji internetowych o otwartym kodzie ลบrรณdลowym, ktรณra wykorzystuje Architektura MVCWydany w 2007 roku i obecnie licencjonowany na platformie Apache, do 2013 roku staล siฤ jednym z najpopularniejszych frameworkรณw na platformie GitHub. Firmy takie jak LinkedIn, WalmartZ tego frameworka korzystajฤ Samsung, Eero i Samsung.
- Wyciฤ g to kolejny darmowy framework webowy napisany w jฤzyku Scala, wydany w 2007 roku. Foursquare korzysta z frameworka Lift. Jest to wysoce wydajny framework, ktรณrego tworzenie jest szybkie.
- Jak udostฤpnia zestaw narzฤdzi do tworzenia wysoce wspรณลbieลผnych, rozproszonych i odpornych aplikacji sterowanych komunikatami na maszynie wirtualnej Java (JVM).
- koty jest bibliotekฤ , ktรณra zapewnia abstraccje programowania funkcyjnego.
- Spark jest zunifikowanym moduลem analitycznym do przetwarzania danych na duลผฤ skalฤ, powszechnie stosowanym w procesach przetwarzania duลผych zbiorรณw danych i uczenia maszynowego.
Wsparcie wspรณลbieลผnoลci
- Wartoลci w Scali sฤ domyลlnie niezmienne, co sprawia, ลผe โโjฤzyk ten doskonale dopasowuje siฤ do ลrodowisk wspรณลbieลผnych.
- Scala ma wiele funkcji, ktรณre czyniฤ jฤ idealnฤ do zastosowaล wspรณลbieลผnych.
- Futures i Promises uลatwiajฤ asynchroniczne przetwarzanie danych, wspierajฤ c w ten sposรณb paralelizm.
- Akka to zestaw narzฤdzi wykorzystujฤ cy model wspรณลbieลผnoลci aktorรณw. Aktorzy podejmujฤ dziaลania po otrzymaniu wiadomoลci.
- Wspรณลbieลผnoลฤ przy uลผyciu wฤ tkรณw z Java jest rรณwnieลผ obsลugiwany w Scali.
- Przetwarzanie strumieniowe to kolejna ลwietna funkcja umoลผliwiajฤ ca ciฤ gลe przetwarzanie danych w czasie rzeczywistym.
Scala ma jedne z najlepszych bibliotek wspรณลbieลผnoลci na rynku Java ekosystem:
- Tubylec Java wฤ tki
- Wลรณkna z bibliotek takich jak Vertx.
- ZIO, biblioteka zawierajฤ ca prymitywy uลatwiajฤ ce radzenie sobie z obliczeniami wspรณลbieลผnymi i asynchronicznymi.
- Pamiฤฤ transakcyjna oprogramowania (STM) dla transakcji.
- Future, ktรณra jest wbudowana w jฤzyk Scala.
Java kontra Scala
Oto gลรณwne rรณลผnice pomiฤdzy Java i Scalฤ.
| Scala | Java |
|---|---|
| Bardziej zwiฤzลe i zwiฤzลe. | Stosunkowo wiฤksze fragmenty kodu. |
| Zaprojektowany i opracowany jako obiektowy i funkcjonalny. Obsลuguje szerokฤ gamฤ funkcji programowania funkcyjnego, takich jak wspรณลbieลผnoลฤ i niezmiennoลฤ. | Pierwotnie rozwijany jako jฤzyk obiektowy i w najnowszych wersjach zaczฤ ล obsลugiwaฤ funkcje programowania funkcyjnego. Nadal nie jest tak silny jak Scala w programowaniu funkcyjnym. |
| Uลผywa modelu aktora do obsลugi wspรณลbieลผnoลci. | Uลผywa konwencjonalnego modelu opartego na wฤ tkach do wspรณลbieลผnoลci. |
| Obsลuguje frameworki takie jak Play i Lift. | Obsลuguje Spring, Grails i wiele innych. |
| Wspiera leniwฤ ocenฤ. | Nie obsลuguje natywnie leniwej oceny. |
| Brak elementรณw statycznych. | Zawiera elementy statyczne. |
| Obsลuguje przeciฤ ลผanie operatorรณw. | 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 interfejsรณw. | Java 8 interfejsรณw ma na celu wypeลnienie luki miฤdzy klasami i interfejsami. |
| Czasami przy uaktualnianiu wersji konieczne jest ponowne napisanie kodu. | Zazwyczaj nie jest konieczne ponowne przepisywanie miฤdzy wersjami. |
| Bezpieczeลstwo typรณw zapewnia wysokฤ niezawodnoลฤ kodu, ale nie gwarantuje absolutnej braku bลฤdรณw. | Silne obciฤ ลผenie statyczneping pomaga zredukowaฤ wiele bลฤdรณw w czasie wykonywania. |
| Ma pewne ograniczenia w zakresie wstecznej kompatybilnoลci pomiฤdzy gลรณwnymi wersjami. | Silna, dลugoterminowa kompatybilnoลฤ wsteczna. |
| Operatory sฤ traktowane jako wywoลania metod. | Operatory majฤ specjalnฤ skลadniฤ i nie sฤ wywoลaniami metod. |
| Obsลuguje dziedziczenie wielokrotne za pomocฤ cech. | Nie obsลuguje wielokrotnego dziedziczenia za pomocฤ klas; zamiast tego uลผywa interfejsรณw. |
| Code jest napisany w formie zwartej. | Code jest napisane w bardziej szczegรณลowej formie. |
| Scala nie zawiera sลowa kluczowego static. | Java zawiera sลowo kluczowe static. |






















