Znamy najbardziej podstawowe elementy składni Scali, będziemy chcieli teraz utworzyć prostą aplikację, która pobiera z internetu dane w standardzie RSS (ang. Really Simple Syndication) i zapisuje je do pliku CSV (ang. Comma-separated values). W ten sposób zobaczymy jak Scala radzi sobie z typowymi zadaniami programistycznymi: przechowywaniem obiektów, wejściem-wyjściem oraz przede wszystkim przetwarzaniem danych w XML-u.
Rozpoczniemy od utworzenia mini bazy danych, która będzie nam służyła do przechowywania danych pobranych z internetu. Zanim się za to jednak weźmiemy, musimy poznać jeszcze kilka elementów języka Scala.
Konwencja JavaBean w wersji Scala
Pierwszą rzeczą, jakiej będziemy potrzebować, to klasa reprezentująca pojedynczą informację udostępnioną przez RSS. Ponieważ istnieje wiele wersji standardu RSS, to będą nas interesowały tylko podstawowe, zawsze występujące dane: tytuł, adres URL i opis informacji. Ponadto każda informacja będzie zawierała unikalny identyfikator.
W Javie zwyczajowo do przechowywania danych różnych typów używamy klas utworzonych w konwencji JavaBean. Klasa taka zawiera pola prywatne reprezentujące dane oraz metody T getNazwPola() i setNazwaPola(T), pozwalające pobrać wartość i zmodyfikować pole o nazwie nazwaPola typu T. Często takie metody nazywa się getterami i setterami. Ze względu na to, że tego typu klasy bardzo często są używane, to albo sami poznamy tajniki szybkiego pisania na klawiaturze, albo zmusimy środowisko programistyczne go wygenerowania metod get i set na podstawie podanych pól.
W Scali to samo można osiągnąć o wiele prościej. Popatrzmy najpierw na Listing 2.
Listing 2. Samodzielna implementacja wzorca JavaBean w Scali. Potrzebne są nam tylko metody służące do pobierania danych – "gettery"
package pl.erudis.feedseater.model import java.net.URL class RSSFeed(id:String, title: String, url:URL, description: String) { def getId = id def getTitle = title def getUrl = url def getDescription = description }
Tym razem tworzymy klasę Scali, nie obiekt. Klasa ma konstruktor pozwalający przekazać do klasy wartości atrybutów RSS. Konstruktor nie jest osobną metoda, jak to najczęściej bywa, zamiast tego odpowiednie parametry są umieszczane wprost w definicji klasy. Jeżeli w konstruktorze mają być wykonane jakieś operacje, to umieszczamy je w ciele klasy zaraz po jej deklaracji. Zmienne zadeklarowane w konstruktorze są automatycznie dostępne w klasie, więc nie ma potrzeby ich kopiowania. W naszym przypadku ograniczyliśmy się tylko do metod get, zwracające wartości pól. Scala pozwala zdefiniować te metody bardzo zwięźle, ale nas to jeszcze nie satysfakcjonuje.
Klasę typu JavaBean można utworzyć jeszcze prościej, korzystając z metadanej (ang. annotation) @BeanProperty. Demonstruje to kod na Listingu 3. W klasie RSSFeedBean metody get i set będą utworzone automatycznie. Szkoda, że Java jeszcze się nie dorobiła takiej metadanej.
Listing 3. Implementacje klasy typu JavaBean w Scali
package pl.erudis.feedseater.model import java.net.URL import java.util.UUID import scala.reflect.BeanProperty class RSSFeedBean(@BeanProperty var title: String, @BeanProperty var url: URL, @BeanProperty var description: String) { private var id: String = UUID.randomUUID.toString def getId = id def this() = this(null, null, null) }
Pole id jest inicjalizowane przy pomocy klasy UUID generującej unikalny łańcuch znaków.
W Scali, jak w każdym przyzwoitym języku obiektowym, klasy mogą mieć więcej niż jeden konstruktor. W Scali reguła jest taka, że główny konstruktor jest definiowany poprzez podanie parametrów w definicji klasy, a pozostałe poprzez definicję metody this. Klasa RSSFeedBean jest wyposażona w taki dodatkowy konstruktor, który pozwala utworzyć obiekt bez podania parametrów: def this() = this(null, null, null).