You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _pl/tour/case-classes.md
+36-94Lines changed: 36 additions & 94 deletions
Original file line number
Diff line number
Diff line change
@@ -6,128 +6,70 @@ discourse: false
6
6
7
7
partof: scala-tour
8
8
9
-
num: 10
9
+
num: 11
10
10
language: pl
11
11
next-page: pattern-matching
12
12
previous-page: multiple-parameter-lists
13
13
---
14
14
15
-
Scala wspiera mechanizm _klas przypadków_. Klasy przypadków są zwykłymi klasami z dodatkowymi założeniami:
15
+
Scala wspiera mechanizm _klas przypadków_ (ang. case class).
16
+
Są one zwykłymi klasami z dodatkowymi założeniami, przez które przejdziemy.
17
+
Klasy przypadków idealnie nadają się do modelowania niezmiennych (niemutowalnych) danych.
18
+
W dalszych rozdziałach przyjrzymy się jak przydają się w [dopasowywaniu wzorców (ang. pattern matching)](pattern-matching.html).
16
19
17
-
* Domyślnie niemutowalne
18
-
* Można je dekomponować poprzez [dopasowanie wzorca](pattern-matching.html)
19
-
* Porównywane poprzez podobieństwo strukturalne zamiast przez referencje
20
-
* Zwięzła składnia tworzenia obiektów i operacji na nich
20
+
## Definiowanie klas przypadków
21
21
22
-
Poniższy przykład obrazuje hierarchię typów powiadomień, która składa się z abstrakcyjnej klasy `Notification`oraz trzech konkretnych rodzajów zaimplementowanych jako klasy przypadków `Email`, `SMS` i `VoiceRecording`:
22
+
Minimalna definicja klasy przypadku wymaga słów kluczowych `case class`, identyfikatora oraz listy parametrów (może być pusta):
23
23
24
24
```tut
25
-
abstract class Notification
26
-
case class Email(sourceEmail: String, title: String, body: String) extends Notification
27
-
case class SMS(sourceNumber: String, message: String) extends Notification
28
-
case class VoiceRecording(contactName: String, link: String) extends Notification
29
-
```
30
-
31
-
Tworzenie obiektu jest bardzo proste: (Zwróć uwagę na to, że słowo `new` nie jest wymagane)
25
+
case class Book(isbn: String)
32
26
33
-
```tut
34
-
val emailFromJohn = Email("john.doe@mail.com", "Greetings From John!", "Hello World!")
27
+
val frankenstein = Book("978-0486282114")
35
28
```
36
29
37
-
Parametry konstruktora klasy przypadków są traktowane jako publiczne wartości i można się do nich odwoływać bezpośrednio:
30
+
Zauważ, że słowo kluczowe `new` nie było konieczne do stworzenia instancji klasy przypadku `Book`.
31
+
Jest tak, ponieważ klasy przypadków posiadają domyślnie zdefiniowaną metodę `apply`, która zajmuje się tworzeniem obiektu klasy.
38
32
39
-
```tut
40
-
val title = emailFromJohn.title
41
-
println(title) // wypisuje "Greetings From John!"
42
-
```
33
+
W przypadku, kiedy tworzymy klasę przypadku zawierającą parametry, są one publiczne i stałe (`val`).
43
34
44
-
W klasach przypadków nie można modyfikować wartości pól. (Z wyjątkiem sytuacji kiedy dodasz `var` przed nazwą pola)
45
-
46
-
```tut:fail
47
-
emailFromJohn.title = "Goodbye From John!" // Jest to błąd kompilacji, gdyż pola klasy przypadku są domyślnie niezmienne
48
35
```
36
+
case class Message(sender: String, recipient: String, body: String)
37
+
val message1 = Message("guillaume@quebec.ca", "jorge@catalonia.es", "Ça va ?")
49
38
50
-
Zamiast tego możesz utworzyć kopię używając metody `copy`:
51
-
52
-
```tut
53
-
val editedEmail = emailFromJohn.copy(title = "I am learning Scala!", body = "It's so cool!")
54
-
55
-
println(emailFromJohn) // wypisuje "Email(john.doe@mail.com,Greetings From John!,Hello World!)"
56
-
println(editedEmail) // wypisuje "Email(john.doe@mail.com,I am learning Scala,It's so cool!)"
message1.sender = "travis@washington.us" // ten wiersz nie skompiluje się
57
41
```
58
42
59
-
Dla każdej klasy przypadku kompilator Scali wygeneruje metodę `equals` implementującą strukturalne porównanie obiektów oraz metodę `toString`. Przykład:
43
+
Nie można ponownie przydzielić wartości do `message1.sender`, ponieważ jest to `val` (stała).
44
+
Alternatywnie, w klasach przypadków można też używać `var`, jednak stanowczo tego odradzamy.
60
45
61
-
```tut
62
-
val firstSms = SMS("12345", "Hello!")
63
-
val secondSms = SMS("12345", "Hello!")
64
-
65
-
if (firstSms == secondSms) {
66
-
println("They are equal!")
67
-
}
46
+
## Porównywanie
68
47
69
-
println("SMS is: " + firstSms)
70
-
```
48
+
Klasy przypadków są porównywane według ich struktury, a nie przez referencje:
71
49
72
-
Wypisze:
50
+
```tut
51
+
case class Message(sender: String, recipient: String, body: String)
73
52
74
-
```
75
-
They are equal!
76
-
SMS is: SMS(12345, Hello!)
53
+
val message2 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
54
+
val message3 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
55
+
val messagesAreTheSame = message2 == message3 // true
77
56
```
78
57
79
-
Jednym z najważniejszych zastosowań klas przypadków (skąd też się wzięła ich nazwa) jest **dopasowanie wzorca**. Poniższy przykład pokazuje działanie funkcji, która zwraca różne komunikaty w zależności od rodzaju powiadomienia:
58
+
Mimo, że `message1` oraz `message2` odnoszą się do innych obiektów, to ich wartości są identyczne.
"You got an email from " + email + " with title: " + title
86
-
case SMS(number, message) =>
87
-
"You got an SMS from " + number + "! Message: " + message
88
-
case VoiceRecording(name, link) =>
89
-
"you received a Voice Recording from " + name + "! Click the link to hear it: " + link
90
-
}
91
-
}
92
-
93
-
val someSms = SMS("12345", "Are you there?")
94
-
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
95
-
96
-
println(showNotification(someSms)) // Wypisuje "You got an SMS from 12345! Message: Are you there?"
97
-
println(showNotification(someVoiceRecording)) // Wypisuje "you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123"
98
-
```
60
+
## Kopiowanie
99
61
100
-
Poniżej bardziej skomplikowany przykład używający `if` w celu określenia dodatkowych warunków dopasowania:
62
+
Możliwe jest stworzenie płytkiej kopii (ang. shallow copy) instancji klasy przypadku używając metody `copy`.
63
+
Opcjonalnie można zmienić jeszcze wybrane parametry konstruktora.
case Email(email, _, _) if email == specialEmail =>
106
-
"You got an email from special someone!"
107
-
case SMS(number, _) if number == specialNumber =>
108
-
"You got an SMS from special someone!"
109
-
case other =>
110
-
showNotification(other) // nic szczególnego, wywołaj domyślną metodę showNotification
111
-
}
112
-
}
113
-
114
-
val SPECIAL_NUMBER = "55555"
115
-
val SPECIAL_EMAIL = "jane@mail.com"
116
-
val someSms = SMS("12345", "Are you there?")
117
-
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
118
-
val specialEmail = Email("jane@mail.com", "Drinks tonight?", "I'm free after 5!")
119
-
val specialSms = SMS("55555", "I'm here! Where are you?")
120
-
121
-
println(showNotificationSpecial(someSms, SPECIAL_EMAIL, SPECIAL_NUMBER)) // Wypisuje "You got an SMS from 12345! Message: Are you there?"
122
-
println(showNotificationSpecial(someVoiceRecording, SPECIAL_EMAIL, SPECIAL_NUMBER)) // Wypisuje "you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123"
123
-
println(showNotificationSpecial(specialEmail, SPECIAL_EMAIL, SPECIAL_NUMBER)) // Wypisuje "You got an email from special someone!"
124
-
println(showNotificationSpecial(specialSms, SPECIAL_EMAIL, SPECIAL_NUMBER)) // Wypisuje "You got an SMS from special someone!"
66
+
case class Message(sender: String, recipient: String, body: String)
67
+
val message4 = Message("julien@bretagne.fr", "travis@washington.us", "Me zo o komz gant ma amezeg")
68
+
val message5 = message4.copy(sender = message4.recipient, recipient = "claire@bourgogne.fr")
69
+
message5.sender // travis@washington.us
70
+
message5.recipient // claire@bourgogne.fr
71
+
message5.body // "Me zo o komz gant ma amezeg"
125
72
```
126
73
127
-
Programując w Scali zachęca się, abyś jak najszerzej używał klas przypadków do modelowania danych, jako że kod, który je wykorzystuje, jest bardziej ekspresywny i łatwiejszy do utrzymania:
128
-
129
-
* Obiekty niemutowalne uwalniają cię od potrzeby śledzenia zmian stanu
130
-
* Porównanie przez wartość pozwala na porównywanie instancji tak, jakby były prymitywnymi wartościami
131
-
* Dopasowanie wzorca znacząco upraszcza logikę rozgałęzień, co prowadzi do mniejszej ilości błędów i czytelniejszego kodu
132
-
74
+
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.
0 commit comments