2015-04-01 137 views
2

我的情況是這樣的:參考抽象類型成員

trait A { 
    type B 
    def foo(b: B) 
} 

trait C[D <: A] { 
    val d: D 
    def createB(): D#B 
    def bar() { 
     d.foo(createB) 
    } 
} 

在REPL,它抱怨

<console>:24: error: type mismatch; 
found : D#B 
required: C.this.d.B 
     a.bar(createB()) 

這有什麼錯呢?和(如果可能的話)如何糾正這個代碼?

回答

3

D#B是一種類型投影,與d.B不一樣。你有一個類型不匹配,因爲在fooB實際上意味着this.B,這與D#B(後者更一般)不一樣。 非正式地,你能想到的D#B爲代表任何可能的類型是抽象類型B可以採取的任何D例如,雖然d.BB指定實例d類型。

在某些情況下,請參閱What does the `#` operator mean in Scala?What is meant by Scala's path-dependent types?

的一種方式,使其編譯它是通過改變createB的返回類型d.B

def createB(): d.B 

然而,在許多情況下,這種解決方案的侷限性太大,因爲你被綁定到特定實例d,這可能不是你想到的。 另一種解決方案是再更換抽象類型與類型參數(雖然它是更詳細):

trait A[B] { 
    def foo(b: B) 
} 

trait C[B, D <: A[B]] { 
    val d: D 
    def createB(): B 
    def bar() { 
    d.foo(createB) 
    } 
} 
0

更新給出this answer我不知道這是否應該被認爲是錯誤或不

這是一個bug:SI-4377。一個明確的類型歸屬產生

trait C[D <: A] { 
    val d: D 
    def createB(): D#B 
    def bar() { 
    (d:D).foo(createB) 
     // [error] found : D#B 
     // [error] required: _3.B where val _3: D 
    } 
} 

它看起來像實施泄漏。有一個解決方法,涉及到鑄造交叉點類型(危險,鑄造是錯誤的等;看到我的其他答案here

trait A { 
    type B 
    def foo(b: B) 
} 
case object A { 
    type is[A0 <: A] = A0 { 
    type B = A0#B 
    } 
    def is[A0 <: A](a: A0): is[A0] = a.asInstanceOf[is[A0]] 
} 

trait C[D <: A] { 
    val d: D 
    def createB(): D#B 
    def bar() { 
    A.is(d).foo(createB) // use it here! 
    } 
}