2013-12-24 3 views
1

Когда я пытался пример животных/Корм ​​для абстрактных типов в Программирование Одерски в Scala,Отсутствует динамическое связывание при абстрактном типе, участвующем в 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. Приведенную выше ошибку можно избежать, если bessy будет Cow вместо Animal: val 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), что компилятор может только предположить, что это животное.

Если вы позволили компилятору знать, что bessy является Cow (val bessy = new Cow), то она будет хорошо тратить траву.

+0

Ну, я принимаю понятие динамической привязки неправильно? 'List' в Java имеет' LinkedList' и 'ArrayList', поэтому, когда вы вызываете' xs.get (idx) 'в' List', вы получаете версию 'ArrayList', когда это реализация' ArrayList'. Я не ожидал, что Скала отклонится от этого. – lcn

+0

@ lcn - Типы должны совпадать. Ваш «простой» пример имеет подпись того же типа для «Parent.sig» и «Child.sig». Наследование (типа «динамического связывания» на C++) работает отлично, но вы должны подчиняться тем типам, которые вы указали. –

+0

, поэтому вы имеете в виду, что при использовании абстрактного типа методы 'eat' будут иметь * разные * подписи и, следовательно, разные методы? Я понимаю, что это лучше подходит для целей абстрактных типов, но должно быть действительно документировано, что здесь есть * NO * динамическое связывание. – lcn