Poznacie teraz coś, co jest absolutną premierą jeśli chodzi o oferowane przez język wysokiego poziomu części składni. Możecie nawet nie przypuszczać, że Kotlin oferuje alternatywną odmianę definiowania klasy. Poza tą "zwykłą", pozwala także na tworzenie klas danych. Zatem opiszę grubo do czego służy "data class" w języku Kotlin, czym to się różni od zwykłej klasy oraz jakie mogą być jej najlepsze zastosowania!

"DATA CLASS" W JĘZYKU KOTLIN. SZCZEGÓŁY KLASY DANYCH

Nowa cecha Kotlina wprowadzona przez twórców otwiera kolejną drogę do zrealizowania tych samych intencji, tylko w mniejszej ilości kodu. Wspomniana klasa danych to nowy budulec, który stworzono z myślą o projektowaniu takich klas, które mają główne zadanie przechowywać wartości danych składowych. Na tym ich rola się nie kończy. Dodatkowo posiadają wbudowane przesłonięcia metod odziedziczonych po klasie "Any" pomagających przy weryfikowaniu identyczności. W dalszej części niniejszego materiału wyjaśni się w jakim celu to zostało zrobione.

PODSTAWOWY ZAPIS

Zacznijmy jak zwykle od najprostszej składni. Aby utworzyć "data class" w języku Kotlin, pisze się to tak:

data class Person(val name : String, val surname : String)
{
	
}

Banał! Dodajecie tylko przedrostek "data" i klasa danych jest gotowa! Można też bez żadnych komplikacji stosować słowo kluczowe "var" dla właściwości. Jeśli klasa nie posiada żadnych instrukcji wewnątrz klamerek, to nawet one można usunąć.

TWORZENIE OBIEKTU DANYCH

Tworzenie obiektu na podstawie "data class" w języku Kotlin nie różni się absolutnie niczym od tworzenia obiektu ze zwykłej klasy więc skieruję tylko do odpowiedniego artykułu i kontynuuję dalej, bo trzeba opisać ważniejsze zagadnienia.

PRZESŁONIĘTE METODY KLASY "ANY"

Oto najważniejszy punkt niniejszego tematu. Klasa danych posiada własne wbudowane implementacje trzech następujących metod odziedziczonych po klasie "Any":

  1. "toString" do formatowania wartości właściwości na strumieniu wyjściowym po podaniu samej nazwy obiektu
  2. "hashCode" do wygenerowania niestandardowego kodu mieszającego
  3. "equals" do porównywania dwóch obiektów czy są takie same

Tłumaczę po kolei co, jak i dlaczego. "data class" w języku Kotlin zostało stworzone w celu możliwości przechowywania (składowania) samych właściwości, choć mogą posiadać swoje metody. Innymi słowy, ta klasa ma nie robić nic innego jak przechowywać dane w jednym miejscu. Takie rzeczy jak wiersz tabeli, stopnie trudności albo konfiguracja ustawień gry, są to doskonałe przykłady zapotrzebowania klas tylko po to, aby móc składować wartości.

Powyższe metody są przesłaniane za naszymi plecami po to, aby zapewnić jeszcze większą wygodę z użytkowania klas danych i nie zawracać sobie głowy koniecznością samodzielnego programowania kiedy program musi uznać, że dwa obiekty są sobie równe. Piję do dwóch kolejnych metod, "hashCode" oraz "equals". Obie metody są od siebie mocno uzależnione kiedy mowa jest o zachowaniu spójności w kwestii identyfikowania prawdziwej identyczności obiektów. Obowiązuje święta zasada: jeśli przesłaniasz "hashCode", to musisz przesłonić także "equals" i vice-versa! Jeśli orientujecie się przy korzystaniu z kolekcji typu "zbiór", to wiecie jak BARDZO jest to ważne zagadnienie.

TOSTRING

Choć "toString" zostało już opisane w poprzednim artykule, trzeba spojrzeć na jej przesłoniętą wersję, która jest dla nas automatycznie generowana na bieżąco. Załóżmy, że mamy taką klasę danych jaką podałem na początku:

data class Person(val name : String, val surname : String)
{
	
}

Klasa posiada dwie dane składowe umieszczone wewnątrz konstruktora podstawowego. Miejsce znajdowania się danej właściwości ma kolosalne znaczenie dla działania wszystkich trzech przesłoniętych metod. W takiej sytuacji, utworzenie obiektu na podstawie naszej klasy danych przy pomocy takiej instrukcji:

val person = Person("Tadeusz", "Kościuszko")

oraz wywołanie funkcji "println" razem z przekazaniem do niej parametru w postaci naszego obiektu:

println(person)

zwróci na wyjściu taki oto ciąg:

Person(name=Tadeusz, surname=Kościuszko)

Czyli mamy nazwę klasy danych i w nawiasie wszystkie dane składowe wraz z etykietami i ich wartościami. Tak "data class" w języku Kotlin przedstawia informacje o obiekcie posługując się metodą "toString".

HASHCODE

Metoda odpowiedzialna za generację kodu mieszającego obiektu stanowi bardzo ważny składnik w zapewnieniu prawidłowego zachowywania spójności i identyfikacji identyczności obiektów. Jej działanie i zastosowanie nie odstaje niczym od języka Java. Ukazywanie wyniku na strumieniu wyjściowym nie ma sensu, gdyż nie jest on tworzony na pokaz. Ta liczba jest dla zbiorów celem sprawdzania czy obiekt jaki chcemy dodać, nie okaże się duplikatem.

EQUALS

O metodzie "equals" też zostawię tylko krótki komentarz, a skoncentruję się bardziej na jej wpływie na porównywanie ze sobą dwóch obiektów. Odnosząc się do swojego artykułu o samej metodzie w języku Java, "equals" zwracający wartość logiczną odpowiada za weryfikowanie obiektu zawartego w parametrze formalnym, czy, kiedy i na jakich warunkach należy dwa obiekty uznać za równe. W przypadku klas danych, jest to najprawdopodobniej koniunkcja wszystkich danych składowych zawartych w konstruktorze podstawowym i porównywanie wartości każdej z nich czy jest identyczna. Jeśli wszystkie wartości danych składowych są takie same, metoda "equals" wówczas "stwierdza", że dwa obiekty klas danych są identyczne.

A teraz praktyka. Spójrzcie na poniższe definicje obiektów pochodzących z tej samej klasy danych:

val personA = Person("Tadeusz", "Kościuszko")
val personB = Person("Tadeusz", "Kościuszko")

Zwróćcie uwagę na dwa rzucające się w oczy szczegóły. Wprowadzamy te same dane, tworzymy dwa osobne obiekty! Jak myślicie, jaki będzie efekt gdy porównamy sobie te obiekty przy pomocy funkcji "println"?

println(personA == personB)

Ciekawy przypadek! Zwróci prawdę!!! Przy normalnych klasach owszem, potraktowano by te obiekty jako różne, jako że to są dwie różne referencje, ale "data class" w języku Kotlin i jej własna wersja metody "equals" została zaprogramowana pod kątem uznawania obu obiektów za równe wtedy, gdy wartości wszystkich danych składowych są identyczne, bez względu na referencję!

ZASADY POSTĘPOWANIA Z KLASAMI DANYCH

Na końcówkę, zbiór kilku zasad i wskazówek jakich trzeba przestrzegać oraz mieć na uwadze, żeby kompilator nie miał przeciwwskazań do uruchomienia naszego kodu, a my żebyśmy się niczemu nie dziwili:

  1. Klasa danych nie może być ani otworzona, ani abstrakcyjna, natomiast może implementować interfejsy i dziedziczyć od innych klas zwykłych
  2. Klasa danych musi mieć co najmniej jedną właściwość w konstruktorze podstawowym, a co za tym idzie musi posiadać sam konstruktor podstawowy
  3. Właściwości klas danych mogą występować poza konstruktorem podstawowym, aczkolwiek nie będą uwzględniane przy porównywaniu ze sobą obiektów ani nie będą podlegać możliwości destrukturyzacji (szczegóły tutaj)
Klasa danych w języku Kotlin

"data class" w języku Kotlin jest jedną z licznych innowacji w składni języków wysokiego poziomu, która umożliwia tworzenie klas których głównym zadaniem jest jedynie przechowywanie wartości danych składowych.


Mam nadzieję, że nie zapomniałem o żadnej najistotniejszej sprawie o jakiej trzeba było napisać, a dotyczy klas danych. Warto to opanować - pozwala uniknąć samodzielnego zajmowania się taką implementacją. W Javie tego nie znajdziecie!

PODOBNE ARTYKUŁY