2016-06-10 2 views
0

Scala n00b здесь. Довольно уверен, что я понимаю PDT, но убедился и столкнулся с проблемой; вот предыдущий вопрос Scala types: Class A is not equal to the T where T is: type T = A с примерами кода, который я воспроизвести здесь:Пример зависимых типов пути не работает

1: class Food 
2: class Fish extends Food 
3: class Grass extends Food 
4: 
5: abstract class Animal { 
    6: type SuitableFood <: Food 
    7: def eat(food: SuitableFood) 
8: } 
9: 
10: class Cow extends Animal { 
    11: type SuitableFood = Grass 
    12: override def eat(food: Grass) {} 
13: } 
14: 
15: val bessy: Animal = new Cow // [1] 
16: 
17: bessy eat (new bessy.SuitableFood) // [2] 

оригинальный плакат сказал, что это компилируется, я считаю, что должен, но это не будет. Если я вставить его в лестницу РЕПЛ успешно создает Бесси [1]:

scala> val bessy: Animal = new Cow 
bessy: Animal = [email protected] 

но [2], дает мне ошибку, которую я не понимаю:

scala> bessy.eat(bessy.SuitableFood) 
<console>:17: error: value SuitableFood is not a member of Animal 
     bessy.eat(bessy.SuitableFood) 
        ^

Если я вставить его в файл и 'scalac' он, я получаю то же самое. Зачем? bessy - объект коровы, type SuitableFood = Grass определен в нем, bessy.SuitableFood - тип класса (не так ли?). Что случилось?

ответ

2
  1. У вас не хватает new в (new bessy.SuitableFood).

  2. После устранения этого bessy определяется иметь тип Animal, не Cow, поэтому компилятор не знаю bessy.SuitableFood является Grass: это просто абстрактный тип, так new bessy.SuitableFood не работает (как new A Безразлично 't, когда A является параметром типа). Например. считают, что какой-либо другой подтип Animal может объявить type SuitableFood = Food, а new Food является незаконным. Я проверил, и он компилируется в 2.10.6, но я считаю, что это ошибка, которая была исправлена.

Поэтому я думал, что «новый bessy.SuitableFood» возвратит подходящую пищу, потому что .SuitableFood будет своего рода виртуального типа, поэтому, когда есть «корова», затем «SuitableFood» будет «трава». Я не вижу значения PDT, если они этого не делают.

Точка ТПР здесь является то, что если вы сделать есть bessy.SuitableFood, bessy может съесть его; и она не может есть spot.SuitableFood (если только компилятор не может статически знаю, что это подтип). Но этот пример не дает никакого способа создать bessy.SuitableFood, потому что нет оснований предполагать (и не указывать компилятору) type SuitableFood - это класс с открытым конструктором без параметров. Вы можете это исправить, добавив метод Animal:

abstract class Animal { 
    type SuitableFood <: Food 
    def eat(food: SuitableFood) 
    def newSuitableFood(): SuitableFood 
} 

class Cow extends Animal { 
    ... 
    def newSuitableFood() = new Grass 
} 

Теперь bessy.eat(bessy.newSuitableFood) будет собирать и работать.

+0

У меня нет точки № 1, там есть «новый» прямо в вашей копии моего кода. Можете ли вы указать, какая строка имеет недостатки? Я добавил номера строк в оригинал, чтобы помочь. Повторите свой второй пункт: «После того, как вы исправите это, bessy определяется как тип Animal, а не Cow, поэтому компилятор не знает bessy.SuitableFood - это Grass« Действительно! Поэтому я подумал, что «новый bessy.SuitableFood» вернет подходящую пищу, потому что .SuitableFood будет своего рода виртуальным типом, поэтому, когда - «Корова», тогда «Подходящий» будет «травой». Я не вижу значения PDT, если они этого не делают. – user3779002

+0

"[2], дает мне ошибку, которую я не понимаю:' scala> bessy.eat (bessy.SuitableFood) '.Здесь нет 'нового'. –

+0

«Следовательно, я думал, что« новый bessy.SuitableFood »вернет подходящую пищу, потому что .SuitableFood будет своего рода виртуальным типом« Но почему вы ожидаете, что этот тип будет иметь конструктор без параметров? Я отредактировал ответ, чтобы объяснить, как это сделать правильно. –

Смежные вопросы