2013-12-24 66 views
1

當我試圖在斯卡拉在馬丁·奧德斯基的編程抽象類型的動物/食品例,抽象類型涉及Scala時沒有動態綁定?

class Food 
abstract class Animal { 
    type SuitableFood <: Food 
    def eat(food:SuitableFood) 
} 
class Grass extends Food 
class Cow extends Animal { 
    type SuitableFood=Grass 
    override def eat(food:SuitableFood) {} 
} 
val bessy:Animal = new Cow 
bessy.eat(new Grass) 

我得到了以下錯誤:

scala> <console>:13: error: type mismatch; 
found : Grass 
required: bessy.SuitableFood 
        bessy.eat(new Grass) 
          ^

原例如通過馬丁bessy.eat(new Fish) ,這肯定會失敗,但我沒想到它也會因爲Grass而失敗。通過讓bessyCow而不是Animalval bessy:Cow = new Cow可以避免上述錯誤。

這是否意味着動態綁定在這裏不起作用?

編輯: 簡單的動態進行定期繼承Scala中綁定:

abstract class Parent { 
    def sig:String = "Parent" 
} 
class Child extends Parent { 
    override def sig:String = "Child" 
} 

而且我有這個,在x:Parent兒童還有:

scala> new Child().sig 
res1: String = Child 

val x:Parent = new Child() 
x: Parent = [email protected] 

x.sig 
res2: String = Child 

回答

6

Scala是靜態類型。一個任意的動物不能吃草,而你剛剛試圖給任意一隻動物喂草。它恰好是一頭牛,但你已經說過(與: Animal),編譯器可能只能假設它是一隻動物。

如果你允許編譯器知道bessyCowval bessy = new Cow),那麼她會吃草很好。

+0

那麼,我採取的動態綁定概念是錯誤的? Java中的'List'具有'LinkedList'和'ArrayList',所以當你在一個'List'上調用一個'xs.get(idx)'時,當它是'ArrayList'的實現時就會得到'ArrayList'版本。我沒有想到Scala會偏離這一點。 – lcn

+0

@lcn - 類型必須匹配。您的「簡單」示例對「Parent.sig」和「Child.sig」具有相同的類型簽名。繼承(C++中的「動態綁定」類型)工作得很好,但你必須服從你給出的類型。 –

+0

所以你的意思是當涉及抽象類型時,'eat'方法會有*不同的簽名,因此是不同的方法?我明白這適合於抽象類型的目的,但應該記錄下這裏有* NO *動態綁定。 – lcn