Reputation: 149
Looking at the source code for immutable.List, I see this
final case class ::[B](override val head: B,
private[scala] var tl: List[B]) extends List[B] {
override def tail : List[B] = tl
override def isEmpty: Boolean = false
}
My understanding of case classes is that this signature is invalid because:
Can somebody explain to me how this is working?
Upvotes: 1
Views: 159
Reputation: 40500
Your assumptions are missing "by default".
By default constructor parameters are vals and public.
I.e., if you say case class Foo(bar: String)
, that'll make bar
a val
and public. Doesn't mean, you can't still say case class Foo(private var bar: String)
Upvotes: 1
Reputation: 67280
It is not forbidden that constructor parameters are non-public. The extractor will still work. The reason it was made package-private is exactly because it is a variable, and so the user cannot alter the value (but only read it through the tail
method). Again this is not forbidden, but just generally strongly discouraged. You should not normally use a var
because the case-class' equality and hash-code depend on the constructor arguments.
List uses a var
here simply to make it easier to assemble new lists. If you look at the source code, you can see this for example in the take
method. And you can also see that tl
is assigned only internally during the construction of new lists. Once they are returned, that variable is not touched any longer, and therefore equality is not broken.
Upvotes: 3