Skip to content

Commit 2cbc0e6

Browse files
authored
Merge pull request #2501 from AlinGabriel/patch-1
Improve code
2 parents 4088889 + 902fb08 commit 2cbc0e6

File tree

1 file changed

+23
-15
lines changed

1 file changed

+23
-15
lines changed

_overviews/core/value-classes.md

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ For example, a fragment of a data type that represents a distance might look lik
6464
def +(m: Meter): Meter = new Meter(value + m.value)
6565
}
6666

67-
Code that adds two distances, such as
67+
Code that adds two distances, such as:
6868

6969
val x = new Meter(3.4)
7070
val y = new Meter(4.3)
@@ -93,7 +93,7 @@ Whenever a value class is treated as another type, including a universal trait,
9393
As an example, consider the `Meter` value class:
9494

9595
trait Distance extends Any
96-
case class Meter(val value: Double) extends AnyVal with Distance
96+
case class Meter(value: Double) extends AnyVal with Distance
9797

9898
A method that accepts a value of type `Distance` will require an actual `Meter` instance.
9999
In the following example, the `Meter` classes are actually instantiated:
@@ -107,7 +107,7 @@ If the signature of `add` were instead:
107107

108108
then allocations would not be necessary.
109109
Another instance of this rule is when a value class is used as a type argument.
110-
For example, the actual Meter instance must be created for even a call to identity:
110+
For example, the actual Meter instance must be created for even a call to `identity`:
111111

112112
def identity[T](t: T): T = t
113113
identity(Meter(5.0))
@@ -122,12 +122,12 @@ The array here contains actual `Meter` instances and not just the underlying dou
122122

123123
Lastly, type tests such as those done in pattern matching or `asInstanceOf` require actual value class instances:
124124

125-
case class P(val i: Int) extends AnyVal
125+
case class P(i: Int) extends AnyVal
126126

127-
val p = new P(3)
127+
val p = P(3)
128128
p match { // new P instantiated here
129129
case P(3) => println("Matched 3")
130-
case P(x) => println("Not 3")
130+
case P(_) => println("Not 3")
131131
}
132132

133133
## Limitations
@@ -141,15 +141,15 @@ A value class ...
141141

142142
1. ... must have only a primary constructor with exactly one public, val parameter whose type is not a user-defined value class. (From Scala 2.11.0, the parameter may be non-public.)
143143
2. ... may not have `@specialized` type parameters.
144-
3. ... may not have nested or local classes, traits, or objects
144+
3. ... may not have nested or local classes, traits, or objects.
145145
4. ... may not define concrete `equals` or `hashCode` methods.
146-
5. ... must be a top-level class or a member of a statically accessible object
146+
5. ... must be a top-level class or a member of a statically accessible object.
147147
6. ... can only have defs as members. In particular, it cannot have lazy vals, vars, or vals as members.
148148
7. ... cannot be extended by another class.
149149

150150
### Examples of Limitations
151151

152-
This section provides many concrete consequences of these limitations not already described in the necessary allocations section.
152+
This section provides many concrete examples of the limitations already described in the previous section.
153153

154154
Multiple constructor parameters are not allowed:
155155

@@ -163,7 +163,7 @@ and the Scala compiler will generate the following error message:
163163

164164
Because the constructor parameter must be a `val`, it cannot be a by-name parameter:
165165

166-
NoByName.scala:1: error: `val' parameters may not be call-by-name
166+
NoByName.scala:1: error: `val` parameters may not be call-by-name
167167
class NoByName(val x: => Int) extends AnyVal
168168
^
169169

@@ -178,25 +178,29 @@ Multiple constructors are not allowed:
178178
def this(y: Double) = this(y.toInt)
179179
^
180180

181-
A value class cannot have lazy vals or vals as members and cannot have nested classes, traits, or objects:
181+
A value class cannot have lazy vals, vars, or vals as members and cannot have nested classes, traits, or objects:
182182

183183
class NoLazyMember(val evaluate: () => Double) extends AnyVal {
184184
val member: Int = 3
185+
var y: Int = 4
185186
lazy val x: Double = evaluate()
186187
object NestedObject
187188
class NestedClass
188189
}
189190

190-
Invalid.scala:2: error: this statement is not allowed in value class: private[this] val member: Int = 3
191+
Invalid.scala:2: error: this statement is not allowed in value class: val member: Int = 3
191192
val member: Int = 3
192193
^
193-
Invalid.scala:3: error: this statement is not allowed in value class: lazy private[this] var x: Double = NoLazyMember.this.evaluate.apply()
194+
Invalid.scala:3: error: this statement is not allowed in value class: var y: Int = 4
195+
var y: Int = 4
196+
^
197+
Invalid.scala:4: error: this statement is not allowed in value class: lazy val x: Double = NoLazyMember.this.evaluate.apply()
194198
lazy val x: Double = evaluate()
195199
^
196-
Invalid.scala:4: error: value class may not have nested module definitions
200+
Invalid.scala:5: error: value class may not have nested module definitions
197201
object NestedObject
198202
^
199-
Invalid.scala:5: error: value class may not have nested class definitions
203+
Invalid.scala:6: error: value class may not have nested class definitions
200204
class NestedClass
201205
^
202206

@@ -208,6 +212,10 @@ Note that local classes, traits, and objects are not allowed either, as in the f
208212
...
209213
}
210214
}
215+
216+
Local.scala:3: error: implementation restriction: nested class is not allowed in value class
217+
class Local
218+
^
211219

212220
A current implementation restriction is that value classes cannot be nested:
213221

0 commit comments

Comments
 (0)