将模式匹配与混入一起使用时的奇怪行为
Weird behavior when using pattern matching with mixins
我可能遗漏了一些明显的东西,但我做不到。
假设我们有以下代码:
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"。模式匹配代码甚至可以在嵌套方法或嵌套函数中,而且它可以工作。但是,如果我将案例 class 移出方法并直接附加到 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 不起作用,如果案例 class(及其所有生成的方法)都在范围内,为什么定义它很重要?在我的真实代码中,我有几个 case classes,在几个模块中,模式匹配器无处不在,所以我不能把所有东西都移动到同一个方法中,我更愿意不必摆脱混入,那么我还有什么其他选择?
我相信有一些事情正在发生。
- Scala 编译器正在尝试找出您要匹配的类型。
- 您混合了顶级类型和本地类型,这似乎混淆了编译器。
在 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)
}
}
}
我希望我能给出更详细(并保证准确)的解释。
我可能遗漏了一些明显的东西,但我做不到。
假设我们有以下代码:
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"。模式匹配代码甚至可以在嵌套方法或嵌套函数中,而且它可以工作。但是,如果我将案例 class 移出方法并直接附加到 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 不起作用,如果案例 class(及其所有生成的方法)都在范围内,为什么定义它很重要?在我的真实代码中,我有几个 case classes,在几个模块中,模式匹配器无处不在,所以我不能把所有东西都移动到同一个方法中,我更愿意不必摆脱混入,那么我还有什么其他选择?
我相信有一些事情正在发生。
- Scala 编译器正在尝试找出您要匹配的类型。
- 您混合了顶级类型和本地类型,这似乎混淆了编译器。
在 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)
}
}
}
我希望我能给出更详细(并保证准确)的解释。