2013-12-24 30 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