У меня есть основной пример из главы 20.7 «Программирование в Скале» (Martin Odersky, Lex Spoon и Bill Venners) по теме «Абстрактные типы». Код ниже в листинге 20.10, за исключением того, что я добавил две последние строки, которые кажутся якобы вытекающим из предыдущего примера:Почему лучший способ избежать попадания в ловушку от абстрактного типа 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: Grass) {}
}
class Fish extends Food
val bossy: Animal = new Cow // If the compiler were helpful, this would error.
bossy.eat(new Grass) // error!
// type mismatch; found: Grass, required: bossy.SuitableFood
Как я уже говорил выше, эти две линии, где властная объявлен как животное на самом деле не в примере, но, по-видимому, очень разумный концептуальный скачок. На уровне абстрактного класса Animal (объявленный тип bossy) член типа ApproFood по-прежнему является абстрактным. Таким образом, ничто не будет удовлетворять компилятору, даже если он выглядит так, как будто он хочет получить зависящий от пути тип при вызове метода.
Если я заявляю о своем Вэл быть типа коровы, работ вызова метода следующим образом:
val bessy: Cow = new Cow
bessy.eat(new Grass) // happy-happy
Учитывая, что нет ничего, что я мог бы поставить в методе «съесть()» призыв к властным (объявленный как Animal), чтобы удовлетворить компилятор, почему компилятор даже разрешает bossy быть объявлен как Animal /, созданный как корова? Другими словами, какое возможное использование, допускающее объявление/экземпляр объекта, но не вызов метода, имеет?
Есть ли «лучшая практика» для этой функции в Scala, учитывая, что абстрактное уточнение типа члена, по-видимому, преднамеренно разрешает что-то, что обычно запрещено в программировании OO? Возможно, кто-то нашел убийцу?
Я очень хочу видеть это поведение как нечто, что имеет смысл. Каков мотивирующий прецедент для этой функции, т. Е. Объявление абстрактного типа, а затем уточнение этого типа в производном классе, так что подтип имеет более утонченный тип, чем супертип?
Хорошо. Это не ошибка компиляции. Вы могли бы по-прежнему сопоставлять совпадение с вашим боссом val, чтобы иметь возможность получить свой правильный подтип и вызвать правильный метод. – Falmarri
Об этом вопросе [здесь] (http://stackoverflow.com/questions/20070998/abstract-type-in-scala), [здесь] (http: // stackoverflow.com/questions/20754143/no-dynamic-binding-when-abstract-type-involved-in-scala), [здесь] (http://stackoverflow.com/questions/32161100/scala-types-class-a-is -not-equal-to-the-t-where-t-is-type-ta) и [здесь] (http://stackoverflow.com/questions/37756383/path-dependent-types-example-doesnt-work). – jwvh