Scala Case类及其默认构造函数

Scala Case类及其默认构造函数,scala,akka,typechecking,Scala,Akka,Typechecking,假设我定义了case类: case class A(id: Int) 然后我突然输入了这个代码: val a = A 问题是——为什么编译器允许这样的写作?在Java中,使用任何参数定义构造函数都会使默认构造函数不可用 编辑: 好的,正如Ende Neu所指出的,a现在包含a.type。 当突然键入a=a可能会打断我的代码时,我如何避免这种情况: a match { case A(id) => do something case _ => I didn't expec

假设我定义了case类:

case class A(id: Int)
然后我突然输入了这个代码:

val a = A
问题是——为什么编译器允许这样的写作?在Java中,使用任何参数定义构造函数都会使默认构造函数不可用

编辑: 好的,正如Ende Neu所指出的,
a
现在包含
a.type
。 当突然键入
a=a
可能会打断我的代码时,我如何避免这种情况:

a match {
   case A(id) => do something
   case _ => I didn't expect fall into here
}
我试图避免陷入Akka消息处理代码中的第二种情况。可能吗


更新:在与Akka+Scala一起工作了一段时间后,我找到了这个问题第二部分的答案。Actor的
receive
方法具有签名
PartialFunction[Any,Unit]
,这意味着输入参数没有类型检查。因此,可以接受任何类型,包括
A.type
。在此上下文中给用户的最佳建议是:向参与者发送消息时要小心。

您正在将
A.type
分配给
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)
我认为这正确地引发了一个例外,因为您想要一个
a
类型的变量,而您最终得到的却是
a.type
类型的变量,这很可能是一个错误,如果您真的想在匹配中区分
a
a.type
,那么类似这样的方法应该会起作用:

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
scala>val a=a
a:a.type=a
scala>一场比赛{
|案例a:a.type=>“a.type”
|案例A:A=>“案例类”
|案例u=>“默认”
|  }
:13:警告:类型测试无效:类型a的值。类型不能也是a
案例A:A=>“案例类”
^
:13:警告:无法访问的代码
案例A:A=>“案例类”
^
res8:String=A.type
scala>val someA=A(1)
someA:A=A(1)
scala>someA匹配{
|案例a:a.type=>“a.type”
|案例A:A=>“案例类”
|案例u=>“默认”
|  }
:12:警告:类型测试无效:类型a的值不能也是a类型
案例a:a.type=>“a.type”
^
res9:String=case类

但正如我所说,这感觉很奇怪,可能有一个更好的解决方案来解决我不知道的这类问题。

您正在将
a.type
分配给
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)
我认为这正确地引发了一个例外,因为您想要一个
a
类型的变量,而您最终得到的却是
a.type
类型的变量,这很可能是一个错误,如果您真的想在匹配中区分
a
a.type
,那么类似这样的方法应该会起作用:

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
scala>val a=a
a:a.type=a
scala>一场比赛{
|案例a:a.type=>“a.type”
|案例A:A=>“案例类”
|案例u=>“默认”
|  }
:13:警告:类型测试无效:类型a的值。类型不能也是a
案例A:A=>“案例类”
^
:13:警告:无法访问的代码
案例A:A=>“案例类”
^
res8:String=A.type
scala>val someA=A(1)
someA:A=A(1)
scala>someA匹配{
|案例a:a.type=>“a.type”
|案例A:A=>“案例类”
|案例u=>“默认”
|  }
:12:警告:类型测试无效:类型a的值不能也是a类型
案例a:a.type=>“a.type”
^
res9:String=case类

但正如我所说,这感觉很奇怪,可能有一个更好的解决方案来解决我不知道的这类问题。

val a:a=a
会告诉你你错了

有很多地方你不能把它留给类型推断

在局部块中,根据定义或我猜是构造,它很小,您可以对类型进行推理

如果您的
a
是成员,则应始终将其归为类型


你永远不必说,很久以后,在代码的一个遥远的部分,我发现一个推断的类型是完全错误的。

val A:A=A
会告诉你你错了

有很多地方你不能把它留给类型推断

在局部块中,根据定义或我猜是构造,它很小,您可以对类型进行推理

如果您的
a
是成员,则应始终将其归为类型


您不必说,很长一段时间后,在代码的一个较远的部分,我发现推断类型完全错误。

您应该问一个与编辑相关的单独问题。这似乎是Akka特有的问题。你应该问一个与编辑相关的单独问题。这似乎是阿克卡特有的问题。我感谢你详尽的回答。看起来我的问题的第二部分应该在另一个线程中,因为它确实是特定于Akka的(发送类似于
recipient!A
的消息会破坏我的代码)。是的,我也这么认为,我的答案只与类型有关,因为我对
Akka
不太了解,当您以akka消息的形式发送类型变量而不是实例时,我无法帮助您。我感谢您详尽的回答。看起来我的问题的第二部分应该在另一个线程中,因为它确实是特定于Akka的(发送类似于
recipient!A
的消息会破坏我的代码)。是的,我也这么认为,我的答案只与类型有关,因为我对
Akka
不太了解,当您将类型变量而不是实例作为akka消息发送时,我无法帮助您。