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
Scala supports the notion of _case classes_. Case classes are just regular classes that are:
15
-
16
-
* Immutable by default
17
-
* Decomposable through [pattern matching](pattern-matching.html)
18
-
* Compared by structural equality instead of by reference
19
-
* Succinct to instantiate and operate on
20
-
21
-
Here is an example for a Notification type hierarchy which consists of an abstract super class `Notification` and three concrete Notification types implemented with case classes `Email`, `SMS`, and `VoiceRecording`.
15
+
Case classes are like regular classes with a few key differences which we will go over. Case classes are good for modeling immutable data. In the next step of the tour, we'll see how they are useful in [pattern matching](pattern-matching.html).
22
16
17
+
## Defining a case class
18
+
A minimal case class requires the keywords `case class`, an identifier, and a parameter list (which may be empty):
23
19
```tut
24
-
abstract class Notification
25
-
case class Email(sourceEmail: String, title: String, body: String) extends Notification
26
-
case class SMS(sourceNumber: String, message: String) extends Notification
27
-
case class VoiceRecording(contactName: String, link: String) extends Notification
28
-
```
20
+
case class Souvenir()
29
21
30
-
Instantiating a case class is easy: (Note that we don't need to use the `new` keyword)
31
-
32
-
```tut
33
-
val emailFromJohn = Email("john.doe@mail.com", "Greetings From John!", "Hello World!")
22
+
val souvenir = Souvenir()
34
23
```
24
+
Notice how the keyword `new` was not used to instantiate the `Message` case class. This is because case classes have an `apply` method by default which takes care of object construction.
35
25
36
-
The constructor parameters of case classes are treated as public values and can be accessed directly.
37
-
38
-
```tut
39
-
val title = emailFromJohn.title
40
-
println(title) // prints "Greetings From John!"
26
+
When you create a case class with parameters, the parameters are public `val`s.
41
27
```
28
+
case class Message(sender: String, recipient: String, body: String)
29
+
val message1 = Message("guillaume@quebec.ca", "jorge@catalonia.es", "Ça va ?")
42
30
43
-
With case classes, you cannot mutate their fields directly. (unless you insert `var` before a field, but doing so is generally discouraged).
44
-
45
-
```tut:fail
46
-
emailFromJohn.title = "Goodbye From John!" // This is a compilation error. We cannot assign another value to val fields, which all case classes fields are by default.
31
+
println(message1.sender) // prints guillaume@quebec.ca
32
+
message1.sender = "travis@washington.us" // this line does not compile
47
33
```
34
+
You can't reassign `message1.sender` because it is a `val` (i.e. immutable). It is possible to use `var`s in case classes but this is discouraged.
48
35
49
-
Instead, you make a copy using the `copy` method. As seen below, you can replace just some of the fields:
50
-
51
-
```tut
52
-
val editedEmail = emailFromJohn.copy(title = "I am learning Scala!", body = "It's so cool!")
53
-
54
-
println(emailFromJohn) // prints "Email(john.doe@mail.com,Greetings From John!,Hello World!)"
55
-
println(editedEmail) // prints "Email(john.doe@mail.com,I am learning Scala,It's so cool!)"
36
+
## Comparison
37
+
Case classes are compared by structure and not by reference:
56
38
```
39
+
case class Message(sender: String, recipient: String, body: String)
57
40
58
-
For every case class the Scala compiler generates an `equals` method which implements structural equality and a `toString` method. For instance:
59
-
60
-
```tut
61
-
val firstSms = SMS("12345", "Hello!")
62
-
val secondSms = SMS("12345", "Hello!")
63
-
64
-
if (firstSms == secondSms) {
65
-
println("They are equal!")
66
-
}
67
-
68
-
println("SMS is: " + firstSms)
41
+
val message2 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
42
+
val message3 = Message("jorge@catalonia.es", "guillaume@quebec.ca", "Com va?")
43
+
val messagesAreTheSame = message2 == message3 // true
69
44
```
45
+
Even though `message2` and `message3` refer to different objects, the value of each object is equal.
70
46
71
-
will print
72
-
47
+
## Copying
48
+
You can create a deep copy of an instance of a case class simply by using the `copy` method. You can optionally change the constructor arguments.
73
49
```
74
-
They are equal!
75
-
SMS is: SMS(12345, Hello!)
50
+
case class Message(sender: String, recipient: String, body: String)
51
+
val message4 = Message("julien@bretagne.fr", "travis@washington.us", "Me zo o komz gant ma amezeg")
52
+
val message5 = message4.copy(sender = message4.recipient, recipient = "claire@bourgogne.fr")
53
+
message5.sender // travis@washington.us
54
+
message5.recipient // claire@bourgogne.fr
55
+
message5.body // "Me zo o komz gant ma amezeg"
76
56
```
77
-
78
-
With case classes, you can utilize **pattern matching** to work with your data. Here's a function that prints out different messages depending on what type of Notification is received:
// You got an SMS from 12345! Message: Are you there?
131
-
// you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123
132
-
// You got an email from special someone!
133
-
// You got an SMS from special someone!
134
-
135
-
```
136
-
137
-
When programming in Scala, it is recommended that you use case classes pervasively to model/group data as they help you to write more expressive and maintainable code:
138
-
139
-
* Immutability frees you from needing to keep track of where and when things are mutated
140
-
* Comparison-by-value allows you compare instances as if they are primitive values - no more uncertainty regarding whether instances of a class is compared by value or reference
141
-
* Pattern matching simplifies branching logic, which leads to less bugs and more readable code.
142
-
143
-
57
+
The recipient of `message4` is used as the sender of `message5` but the `body` of `message4` was copied directly.
0 commit comments