我可能遗漏了一些显而易见的东西,但我无法做到这一点。
假设我们有以下代码:
object T {
def method: Unit = {
trait Mixin
case class Foo(foo: String)
val f = new Foo("hi") with Mixin
f match {
case Foo(s) => println(s)
}
}
}
当我调用Test.method时,这会编译并打印“hi”。模式匹配代码甚至可以在嵌套方法或嵌套函数中,并且它可以工作。但是,如果我将case类移到方法之外并直接附加到T2:
object T2 {
case class Foo(foo: String)
def method: Unit = {
trait Mixin
val f = new Foo("hi") with Mixin
f match {
case Foo(s) => println(s)
}
}
}
它会抛出以下错误:
Error:(183, 12) constructor cannot be instantiated to expected type;
found : T2.Foo
required: T2.Foo with Mixin
case Foo(s) => println(s)
^
如果现在我不使用Mixin,只使val f = new Foo(“hi”),它再次正常工作。如果我尝试匹配其类型,它也有效:
val f = new Foo("hi") with Mixin
f match {
case f: Foo => println("I am a Foo")
}
如果案例类(及其所有生成的方法)都在范围内,为什么T2不起作用?为什么定义它的位置很重要?在我的实际代码中,我有几个案例类,在几个模块中,模式匹配器到处都是,所以我不能只在同一个方法中移动所有内容,如果我不需要,我更愿意摆脱mixins,我还有其他选择吗?
答案 0 :(得分:1)
我相信有一些事情正在发生。
在T
中,Foo
和Mixin
都在您的方法范围内声明为本地。在其范围之外不需要本地类型(在本例中为method
)。因为一切都在相同的范围内,所以编译器很容易弄清楚你想要做什么。
在T2
中,Foo
在顶级声明,但Mixin
仍然是本地类型。这似乎摒弃了编译器。您可以通过专门键入值f
到Foo
来帮助编译器,这将允许您的代码段进行编译。
object T2 {
case class Foo(foo: String)
def method: Unit = {
trait Mixin
val f: Foo = new Foo("hi") with Mixin
f match {
case Foo(s) => println(s)
}
}
}
我希望我能提供更详细(并保证准确)的解释。