Suppose, I defined the case class:
case class A(id: Int)
Then I suddenly typed this code:
val a = A
The question is - why compiler allows such writings? In Java, defining constructor with any parameters, makes the default constructor not available.
EDIT:
Ok, as Ende Neu pointed, the a
now contains A.type
.
How can I avoid scenario, when suddenly typing a = A
may break my code in:
a match {
case A(id) => do something
case _ => I didn't expect fall into here
}
I'm trying to avoid to fall into the second case in my Akka message processing code. Is it possible?
UPDATE: After some time spent on working with Akka + Scala I figured out, the answer to the second part of this question. Actor's receive
method has signature PartialFunction[Any, Unit]
, that means there's no typecheck for the input parameter. So any type is accepted, including A.type
. Best advice to the user in this context: be careful when sending the messages to actors.
You are assigning A.type
to a
:
scala> case class A(id: Int)
defined class A
scala> val a = A
a: A.type = A
scala> a()
<console>:11: error: not enough arguments for method apply: (id: Int)A in object A.
Unspecified value parameter id.
a()
^
scala> a(1)
res1: A = A(1)
After the assignment a
is of type A.type
, then you can use a
to construct new instances of the case class A
, but you will still need to specify the id
parameter.
Regarding your edit:
a match {
case A(id) => do something
case _ => I didn't expect fall into here
}
I think this correctly throws an exception in this case since you wanted a variable of type A
and instead you ended up with a variable of type A.type
, which is most probably a mistake, if you really want to differentiate between A
and A.type
in your match something like this should work:
scala> val a = A
a: A.type = A
scala> a match {
| case a: A.type => "A.type"
| case someA: A => "case class"
| case _ => "default"
| }
<console>:13: warning: fruitless type test: a value of type A.type cannot also be a A
case someA: A => "case class"
^
<console>:13: warning: unreachable code
case someA: A => "case class"
^
res8: String = A.type
scala> val someA = A(1)
someA: A = A(1)
scala> someA match {
| case a: A.type => "A.type"
| case someA: A => "case class"
| case _ => "default"
| }
<console>:12: warning: fruitless type test: a value of type A cannot also be a A.type
case a: A.type => "A.type"
^
res9: String = case class
But as I said, this feels weird, probably there's a better solution to this kind of problems that I don't know.