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. |






















