2016-01-22 76 views
3

我可能错过了一些明显的东西,但我无法完成这项工作。与mixin使用模式匹配时的奇怪行为

假设我们有下面的代码:

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。模式匹配代码甚至可以在嵌套方法或嵌套函数内部工作。但是,如果我移动的情况下,类方法外,并直接连接到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) 
     ^

如果现在我不使用密新,只有让VAL f = new Foo(“hi”),它再次正常工作。它也可以,如果我尝试以匹配其类型:

val f = new Foo("hi") with Mixin 
f match { 
    case f: Foo => println("I am a Foo") 
} 

为什么不T2工作,如果案件类(及其所有生成的方法)都在范围,为什么会身在何处,它是界定?在我的真实代码中,我有几个case类,有几个模块,并且模式匹配器遍布各处,所以我不能只用同一个方法来移动所有的东西,而且我更喜欢如果我不需要摆脱mixins,我还有什么其他的选择?

回答

1

我相信有一些事情正在进行。

  • Scala编译器试图找出你匹配的是什么类型。
  • 你已经混合了顶级类型和本地类型,这似乎混淆了编译器。

T,既FooMixin在你的方法的范围内局部声明。本地类型不在其范围之外(在这种情况下,method)。因为一切都在同一个范围内,所以编译器很容易找出你想要做的事情。

T2中,Foo被声明在顶层,但Mixin仍然是本地类型。这似乎甩掉了编译器。您可以通过专门输入值fFoo来帮助编译器,这将允许您的代码段进行编译。

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) 
    } 
    } 
} 

我希望我可以给一个更详细的(并且保证准确)解释。

+0

我忘了提及:我可以将特性Mixin移动到所有我想要的位置,编译器从不抱怨,只有在移动案例类时。如果case类在方法内,并且mixin在外部,则编译好。另外,感谢您的解决方案。到处都会有点不舒服,但至少它会奏效。 – Julkson