Scala wspiera mechanizm klas przypadków (ang. case class). Są one zwykłymi klasami z dodatkowymi założeniami, przez które przejdziemy. Klasy przypadków idealnie nadają się do modelowania niezmiennych (niemutowalnych) danych. W dalszych rozdziałach przyjrzymy się jak przydają się w dopasowywaniu wzorców (ang. pattern matching).
Definiowanie klas przypadków
Minimalna definicja klasy przypadku wymaga słów kluczowych case class
, identyfikatora oraz listy parametrów (może być pusta):
case class Book(isbn: String)
val frankenstein = Book("978-0486282114")
Zauważ, że słowo kluczowe new
nie było konieczne do stworzenia instancji klasy przypadku Book
.
Jest tak, ponieważ klasy przypadków posiadają domyślnie zdefiniowaną metodę apply
, która zajmuje się tworzeniem obiektu klasy.
W przypadku, kiedy tworzymy klasę przypadku zawierającą parametry, są one publiczne i stałe (val
).
case class Message(sender: String, recipient: String, body: String)
val message1 = Message("[email protected]", "[email protected]", "Ça va ?")
println(message1.sender) // wypisze [email protected]
message1.sender = "[email protected]" // ten wiersz nie skompiluje się
Nie można ponownie przydzielić wartości do message1.sender
, ponieważ jest to val
(stała).
Alternatywnie, w klasach przypadków można też używać var
, jednak stanowczo tego odradzamy.
Porównywanie
Klasy przypadków są porównywane według ich struktury, a nie przez referencje:
case class Message(sender: String, recipient: String, body: String)
val message2 = Message("[email protected]", "[email protected]", "Com va?")
val message3 = Message("[email protected]", "[email protected]", "Com va?")
val messagesAreTheSame = message2 == message3 // true
Mimo, że message1
oraz message2
odnoszą się do innych obiektów, to ich wartości są identyczne.
Kopiowanie
Możliwe jest stworzenie płytkiej kopii (ang. shallow copy) instancji klasy przypadku używając metody copy
.
Opcjonalnie można zmienić jeszcze wybrane parametry konstruktora.
case class Message(sender: String, recipient: String, body: String)
val message4 = Message("[email protected]", "[email protected]", "Me zo o komz gant ma amezeg")
val message5 = message4.copy(sender = message4.recipient, recipient = "[email protected]")
message5.sender // [email protected]
message5.recipient // [email protected]
message5.body // "Me zo o komz gant ma amezeg"
Odbiorca wiadomości 4 message4.recipient
jest użyty jako nadawca wiadomości 5 message5.sender
, ciało wiadomości 5 zostało skopiowane bez zmian z wiadomości 4.
Contributors to this page:
Contents
- Wprowadzenie
- Podstawy
- Hierarchia typów
- Klasy
- Domyślne wartości parametrów
- Parametry nazwane
- Cechy
- Krotki
- Kompozycja klas przez domieszki
- Funkcje wyższego rzędu
- Funkcje zagnieżdżone
- Rozwijanie funkcji (Currying)
- Klasy przypadków
- Dopasowanie wzorców (Pattern matching)
- Obiekty singleton
- Wzorce wyrażeń regularnych
- Obiekty ekstraktorów
- For Comprehensions
- Klasy generyczne
- Wariancje
- Górne ograniczenia typów
- Dolne ograniczenia typów
- Klasy wewnętrzne
- Typy abstrakcyjne
- Typy złożone
- Jawnie typowane samoreferencje
- Parametry domniemane
- Konwersje niejawne
- Metody polimorficzne
- Lokalna inferencja typów
- Operatory
- Parametry przekazywane według nazwy
- Adnotacje
- Pakiety i importy
- Obiekty pakietu