Scala
Dziś chciałbym przedstawić wszystkim tutorial odnośnie języka Scala.
Instalacja
Instalację Scali możemy przeprowadzić na różne sposoby.
curl -fL https://github.com/coursier/coursier/releases/latest/download/cs-x86_64-pc-linux.gz | gzip -d > cs && chmod +x cs && ./cs setup
To jest instalacja w systemie Linux. Na oficjalnej stronie języka Scala czyli https://www.scala-lang.org/download/ mamy instrukcję instalacji na wszystkie systemy operacyjne. Czyli instalacja przez brew na macOS, instalka dla Windowsa i inne.
Dobrze jest też mieć zainstalowaną Javę.
sudo apt-get install default-jdk
Następnie wpisujemy polecenie: sudo apt-get install scala
Środowisko programistyczne
Są różne sposoby uruchamiana programów napisanych w języku Scala. Ja uważam, że obecnie najlepszym jest używanie środowiska programistycznego. Polecam Intellij Idea Community. To akurat środowisko jest w pełni darmowe i ma wiele ciekawych funkcji. Można je pobrać ze strony internetowej https://www.jetbrains.com/idea/download/?section=linux. Istnieje też wersja Ultimate, ale do Scali wystarczy ta wersja Community.
Projekt
No to tworzymy projekt. Mamy zainstalowany Intellij. Uruchamiamy środowisko. Znajdujemy opcję New > Project czy coś takiego. Wybieramy opcję Scala, czyli że chcemy utworzyć projekt w języku Scala. Wybieramy SDK. Jak nie mamy to środowisko może pomóc nam je zainstalować. Dajemy nazwę projektu i tworzymy nasz pierwszy projekt w języku Scala.
Klasa Main
Na razie nie będę wnikał w klasy. Jest to część języka Scala. Na tą chwilę powinno być to wiadome, że każdy projekt posiada klasę uruchomieniową. Najlepiej nazwać ją Main, co oznacza, że jest to klasa główna, która uruchamia program, nasz program. Otwieramy ją. W niej mamy metodę main(). Niby ta klasa to jest tzw. object, no ale to też jest klasa. W metodzie main() wpisujemy wszystkie instrukcje, które chcemy uruchomić. Następnie naciskamy kombinację Shift + F10 i uruchamiamy program.
Klasy
A więc tak, w języku Scala istnieją tzw. klasy. Klasa definiuje obiekt. Zawiera metody, które definiują zachowanie obiektu. W folderze src tworzymy nowe pakiety i klasy. Kiedyś pakiety oznaczało się w taki sposób: com.domena.modul. Teraz to jest dowolne. Czyli prawy przycisk myszy na folder src > New > package. Nazywamy pakiet. W tym pakiecie tworzymy klasę, czyli new > Scala class. Dobrze by było gdyby nazwy klas zaczynały się wielką literą i odwzorowywały to co robi dana klasa. Czyli jak np. klasa wyświetla tekst to nazwiemy ją powiedzmy drukarka.
W klasie tworzymy metodę. Tworzymy ją tak: def
package kurs
class Kurs {
def wyswietlanie(): Unit = {
}
}
Ta metoda jeszcze nic nie robi. No to napiszę w niej sobie instrukcję, która wyświetla dowolny tekst. W Scali jest to instrukcja println().
package kurs
class Kurs {
def wyswietlanie(): Unit = {
println("Witaj Scala!")
}
}
No dobra, jest klasa, jest metoda, ale trzeba ją jeszcze uruchomić. Przechodzę do klasy Main i tworzę odpowiednie instrukcje. Podaję obiekt i uruchamiam metodę.
Obiekty mają takie przyjęte w Scali dwa typy: val i var. Obiekt val tworzymy raz i jego instancji już nie zmieniamy, a w obiekcie var możemy zmieniać instancję.
Czyli w metodzie main() klasy Main tworzymy obiekt: val kurs = new Kurs. Następnie wywołujemy metodę wyświetlanie: kurs.wyswietlanie().
Możemy uruchomić program.
Spośród różnych typów danych możemy wymienić:
- Integer - liczby całkowite
- Float - liczby zmiennoprzecinkowe
- Double - liczby zmiennoprzecinkowe
- Long - nieco dłuższe intidżery
- String - ciągi znaków
Wszystkie jednak typy oznacza się przez val lub var. Jak dodatkowo chcemy oznaczyć typ zmiennej to robimy to w ten sposób: var zmienna: Double = 0.0d.
To co, można wykonywać typowe operacje arytmetyczne. Można wykonywać rozszerzone działania przez bibliotekę math. Jest obsługa plików, listy, tablice. Można powiedzieć, że Scala to taka Java na resorach. To co parę przykładzików.
Pobieranie informacji
def pobierz_info(): Unit = {
var znaki = ""
print("Podaj swoje imię: ")
znaki = scala.io.StdIn.readLine()
println("Witaj " + znaki)
}
Tą metodę można sobie skopiować i wkleić do poprzedniej klasy. Metoda pobiera imię od użytkownika. Imię wpisuje się z klawiatury.
Kalkulator
Uczyńmy więc sobie prosty kalkulator, na nasze podobieństwo, podobnemu kalkulatorowi np. z Windowsów, itd.
def dzialanie(zm1: Double, zm2: Double, dz: String): Double = {
var wynik: Double = 0.0d
if (dz.compareTo("+") == 0) { wynik = zm1 + zm2 }
if (dz.compareTo("-") == 0) { wynik = zm1 - zm2 }
if (dz.compareTo("*") == 0) { wynik = zm1 * zm2 }
if (dz.compareTo("/") == 0) { wynik = zm1 / zm2 }
if (dz.compareTo("%") == 0) { wynik = zm1 % zm2 }
wynik
}
Tu już użyłem instrukcji if. Można użyć if-else. Czyli mamy trzy argumenty. Pierwszy i drugi to składniki działania, a trzeci wskazuje na rodzaj działania jakie chcemy wykonać. Widać metoda zwraca obiekt typu Double. Dosyć ciekawa metoda.
Listy
Scala ma wiele rodzajów list. Ja tutaj właśnie znalazłem bardzo ciekawy rodzaj listy o nazwie ListBuffer. Używam go i powiem, że jak dla mnie najlepszy rodzaj spośród wszystkich list. Intellij wyświetla mi tutaj aż 22 rodzaje tzw. Tupli. Sporo. No ale nic, przejdźmy do sedna.
var lista = new ListBuffer[Double]. W nawiasie kwadratowym podaję typ danych.
- lista += 1 - umieszczenie w liście elementu o wartości 1
- lista (0) - dostęp do wybranego elementu listy, w tym przypadku do elementu o indeksie 0
- lista.size() - rozmiar
- lista.clear() - wyczyszczenie listy
- lista.remove(0) - usunięcie wybranego elementu, w tym przypadku o indeksie 0
- lista.insert(0, 10.1) - wstawienie elementu, tutaj do indeksu 0 wstawiamy element o wartości 10.1
- lista.update(0, 12.3) - aktualizacja wybranego elementu
- lista.isEmpty - sprawdzanie, czy lista jest pusta
Są to takie podstawowe metody dla listy.
Pętle
Pętla to taka instrukcja, która powstarza się sama określoną ilość razy. Pętla while:
def petla(): Unit = {
var indeks = 0
while ( indeks < 10 ) {
println(indeks)
indeks = indeks + 1
}
}
W pętli for możemy odczytać całą listę:
for (element <- lista) {
println(element)
}
Wątki
Wątki to obiekty, które mogą zostać uruchomione w tym samym czasie.
class Watek extends Thread {
override def run(): Unit = {
println("Wątek")
}
}
Metoda main():
var watek1 = new Watek
var watek2 = new Watek
var watek3 = new Watek
watek1.start()
watek2.start()
watek3.start()
Jak widać klasa Watek dziedziczy po klasie Thread. Dziedziczymy poprzez dopisanie słowa kluczowego extends. Następnie nadpisujemy metodę override i tam właśnie mówimy wątkowi co ma robić. Możemy wątki spakować do listy i uruchamiać kiedy chcemy.
Pliki
Działania na plikach w Scali są dosyć proste.
Zapis pliku
var sciezka = "plik1.txt"
var dane = "Siała baba mak\nNie wiedziała jak"
new PrintWriter(sciezka) { write( dane ); close() }
Odczyt pliku
def odczytaj_plik (sciezka: String = ""): ListBuffer[String] = {
val zrodlo: BufferedSource = Source.fromFile(sciezka);
val lista = ListBuffer("")
lista.remove(0)
try {
for (linia <- zrodlo.getLines()) {
lista += linia
}
} finally {
zrodlo.close()
}
lista
}
A wkleiłem już całą metodę, niech będzie.
Usuwanie plików.
var plik = new File(sciezka)
val istnieje = plik.exists()
if ( istnieje ) {
plik.delete()
Lista plików.
val folder: File = new File(sciezka)
var lista = folder.list().toList
Plik istnieje.
val plik = new File(sciezka)
val istnieje = plik.exists()
Stworzenie folderu.
new File(sciezka).mkdir()
Data
Chcemy wyświetlić datę w Scali? Nie ma problemu. Użyjmy do tego klasy ZonedDateTime.
- ZonedDateTime.now().getYear - aktualny rok
Dalej nie pokazuję, bo są od tego dokumentacje.
Grafika
val size = (500, 500)
val canvas = new BufferedImage(size._1, size._2, BufferedImage.TYPE_INT_RGB)
val g = canvas.createGraphics()
g.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
java.awt.RenderingHints.VALUE_ANTIALIAS_ON) // antialiasing
g.setColor(Color.CYAN)
g.fill(new Rectangle2D.Double(20.0, 400.0, 50.0, 20.0)) // prostokat
g.draw(new Rectangle2D.Double(400.0, 400.0, 50.0, 20.0)) // prostokat bez wypelnienia
g.setColor(new Color(0, 0, 255))
g.draw(new Line2D.Double(50.0, 50.0, 250.0, 400.0)) // linia
// teksty
g.setColor(new Color(0, 128, 0))
g.setFont(new Font("Batang", Font.PLAIN, 20))
g.drawString("Hello World!", 155, 225)
g.drawString("안녕 하세요", 175, 245)
g.setColor(Color.RED)
g.fill(new Ellipse2D.Double(30.0, 30.0, 40.0, 40.0)) // elipsa
g.fill(new Ellipse2D.Double(230.0, 380.0, 40.0, 40.0))
g.dispose() // zakonczenie rysowania
javax.imageio.ImageIO.write(canvas, "png", new java.io.File("drawing.png")) // zapisanie grafiki do pliku
Interfejs
Interfejs graficzny pomaga w zarządzaniu naszym programem.
var frame = new JFrame();
frame.setSize(350, 350);
frame.setDefaultCloseOperation(2);
frame.setTitle("Okno");
frame.setVisible(true);