2016-01-22 46 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