2011-11-12 177 views
2

說我有兩個類具有相同標識符的參數化類型斯卡拉:抽象類型和混入

trait A { 
    type O 
    def f(a: Int, os: Seq[O]): Int 
    } 

    trait B { 
    type O 
    def g(a: Int, o: O): Int = { h1(o) + h2(a) } 
    def h1(o: O): Int 
    def h2(a: Int): Int = {a/2} 
    } 

我想創建一個子類,將「嫁」兩

trait C extends A with B { 
    def f(a: Int, os: Seq[O]): Int = { 
     os.map{ o => g(a, o) }.sum 
    } 
    } 

最後,我建立了C

class D extends C { 
    type O = Int 
    def h1(o: O): Int = {5 * o} 
    } 

的執行情況的書面C我不ÿ等知道是什麼類型的O - 不過,我想限制A.O == B.O,使得「有意義」在A.f實現使用B.g。我試圖實現這一點,它令人驚訝的好像斯卡拉認爲,只有過一個type O

val d = new D 
    println(d.f(1, Seq(1,2,3))) 

對我來說,這似乎是不正確 - 爲什麼要A.OB.O同意嗎?

編輯 我也想指出,如果你是不是把約束O對像這樣,

case class Z() 
    case class Z1() extends Z 
    case class Z2() extends Z1 

    trait A { 
    type O <: Z 
    } 

    trait B { 
    type O >: Z2 
    } 


class D extends C { 
    type O = Z1 

編譯失敗。但是,如果你把這個,而不是,

trait A { 
    type O <: Z 
    } 

    trait B { 
    type O <: Z1 
    } 
    class D extends C { 
    type O = Z2 

編譯成功,一切運行良好。

回答

4

我認爲斯卡拉總是「結婚」的成員 - 無論是類型和值的成員 - 性狀兩者混合時:

trait A { type T = Int } 
trait B { type T = String } 

object C extends A with B 

給出性狀A

壓倒一切的T型,等於Int; 類型T的性狀B,它等於字符串需要'覆蓋」修飾符

(這是斯卡拉如何與多重繼承問題涉及 - 不管標識符多少次混合,它只存在一次)。因爲Scala需要一點幫助在C建立類型界限

+1

換句話說,「不要忘了Scala的類型線性化」! – duckworthd

2

你第二個例子失敗。我想也許它應該足夠聰明,以便自己弄清楚,但是更熟悉類型理論的人將不得不解釋爲什麼或者爲什麼不。 C的這個定義應該可以工作:

trait C extends A with B { 
    type O >: Z2 <: Z // restrict O's type so it's valid for both A and B 
} 

Scala處理抽象類型與處理抽象方法類似。同一名稱(和簽名)從多個特徵中拉出的方法被一起覆蓋。以經典反例爲例,衍生自Ye Olde C++ Programming Language中給出的示例。

trait Cowboy { 
    /** Shoot something */ 
    def draw 
} 

trait Window { 
    /** Draw something */ 
    def draw 
} 

class CowboyWindow { 
    /** Probably best to draw something on the screen, then shoot it */ 
    def draw { 
    // ... 
    } 
} 

在它假設只有一個type O在你的代碼的方式,它假定只有一個方法draw在此代碼。在這種情況下,這個假設是有問題的,因爲你最終可能會在腳下射擊自己。

正如你在你的例子中發現的,通常這個假設是最好的(想想多個接口聲明一個close()方法)。但是如果這個假設對於某些類來說是有問題的,就像CowboyWindow那樣,你可以用繼承來代替繼承。

+0

處理抽象類型的上下界並不是我的問題的意圖,但很高興知道這一切!我沒有意識到你可以同時放置一個類型的下限/上限 – duckworthd