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 regular classes which export their constructor parameters and which provide a recursive decomposition mechanism via [pattern matching](pattern-matching.html).
13
+
Scala supports the notion of _case classes_. Case classes are just regular classes that are:
14
14
15
-
Here is an example for a class hierarchy which consists of an abstract super class `Term` and three concrete case classes `Var`, `Fun`, and `App`.
15
+
* Immutable by default
16
+
* Decomposable through [Pattern Matching](pattern-matching.html)
17
+
* Compared by structural equality instead of by reference
18
+
* Succinct to instantiate and operate on
19
+
20
+
This is achieved through auto-generated code by the Scala compiler.
21
+
22
+
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`.
16
23
17
24
```tut
18
-
abstract class Term
19
-
case class Var(name: String) extends Term
20
-
case class Fun(arg: String, body: Term) extends Term
21
-
case class App(f: Term, v: Term) extends Term
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
22
29
```
23
30
24
-
This class hierarchy can be used to represent terms of the [untyped lambda calculus](https://en.wikipedia.org/wiki/Lambda_calculus). To facilitate the construction of case class instances, Scala does not require that the `new` primitive is used. One can simply use the class name as a function.
31
+
Instantiating a Case class is easy: (Note that we don't need to use the `new` keyword)
32
+
33
+
```tut
34
+
val emailFromJohn = Email("[email protected]", "Greetings From John!", "Hello World!")
35
+
```
25
36
26
-
Here is an example:
37
+
The constructor parameters of case classes are treated as public values and can be accessed directly.
27
38
28
39
```tut
29
-
Fun("x", Fun("y", App(Var("x"), Var("y"))))
40
+
val title = emailFromJohn.title
41
+
println(title) // prints "Greetings From John!"
30
42
```
31
43
32
-
The constructor parameters of case classes are treated as public values and can be accessed directly.
44
+
With case classes, you cannot mutate their fields directly. Instead, you make a copy using the `copy` method.
45
+
As seen below, you can replace just some of the fields:
33
46
34
47
```tut
35
-
val x = Var("x")
36
-
println(x.name)
48
+
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.
49
+
50
+
val editedEmail = emailFromJohn.copy(title = "I am learning Scala!", body = "It's so cool!")
51
+
52
+
println(emailFromJohn) // prints "Email([email protected],Greetings From John!,Hello World!)"
53
+
println(editedEmail) // prints "Email([email protected],I am learning Scala,It's so cool!)"
37
54
```
38
55
39
56
For every case class the Scala compiler generates an `equals` method which implements structural equality and a `toString` method. For instance:
It only makes sense to define case classes if pattern matching is used to decompose data structures. The following [object](singleton-objects.html) defines a pretty printer function for our lambda calculus representation:
76
+
With Case Classes, all the necessary machinery required for using them in **Pattern Matching** is automatically generated by the compiler.
77
+
Here's a function that prints out different messages depending on what type of Notification is received:
val someVoiceRecording = VoiceRecording("Tom", "voicerecording.org/id/123")
120
+
val specialEmail = Email("[email protected]", "Drinks tonight?", "I'm free after 5!")
121
+
val specialSms = SMS("55555", "I'm here! Where are you?")
122
+
123
+
// prints:
124
+
// You got an SMS from 12345! Message: Are you there?
125
+
// you received a Voice Recording from Tom! Click the link to hear it: voicerecording.org/id/123
126
+
// You got an email from special someone!
127
+
// You got an SMS from special someone!
128
+
86
129
```
87
130
88
-
In our example, the function `printTerm` is expressed as a pattern matching statement starting with the `match` keyword and consisting of sequences of `case Pattern => Body` clauses.
89
-
The program above also defines a function `isIdentityFun` which checks if a given term corresponds to a simple identity function. This example uses deep patterns and guards. After matching a pattern with a given value, the guard (defined after the keyword `if`) is evaluated. If it returns `true`, the match succeeds; otherwise, it fails and the next pattern will be tried.
131
+
_Case Classes_ is one of the biggest reasons why Scala code can be both concise and readable. With immutability and structural equality, working with
132
+
case classes are just like working with primative values (Int, Double, etc), which in turn makes writing programs in a functional style much simpler
0 commit comments