【问题标题】:Scala types: Class A is not equal to the T where T is: type T = AScala 类型:A 类不等于 T 其中 T 是:类型 T = A
【发布时间】:2015-08-22 21:46:21
【问题描述】:

我正在阅读《Scala 编程》一书的第 20.7 节,我想知道为什么这段代码会编译:

class Food
class Fish extends Food
class Grass extends Food

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


class Cow extends Animal {
  type SuitableFood = Grass
  override def eat(food: Grass) {}
}


val bessy: Animal = new Cow

bessy eat (new bessy.SuitableFood)

这段代码没有(其余代码和之前一样,只是最后一行改变了):

bessy eat (new Grass)

据我了解,草的类型与 Cow.SuitableFood 相同。

另外,关于这个例子我还有一个问题:

如果 bessy 是 Animal 类型,编译器怎么知道它需要一个类型合适的食物 -> 草而不是一个类型的食物?因为试图提供一个新的食物给我一个类型不匹配的编译错误,但是类 Animal 需要一个类型 Food 并且明确定义了 bessy 的类型:Animal

【问题讨论】:

  • 建议:在这个问题中添加标签path-dependent-type。这可能会吸引更了解这种困难的人的回答。 (我自己还在为依赖路径的类型而苦苦挣扎。)
  • @BenKovitz 已添加,谢谢。

标签: scala types path-dependent-type


【解决方案1】:

这是因为 bessie 被声明为 Animal 而不是 Cow。 bessie.SuitableFood 是“路径依赖类型”(见下文)。

试试这个:

val clarabelle: Cow = new Cow

clarabelle eat (new Grass)

这是可行的,因为编译器可以从 clarabelle 的声明类型中推断出 clarabelle.SuitableFood = Grass。

由于bessie 被声明为Animal,而不是Cow,编译器无法安全地推断出bessie.SuitableFood = Grass。* 当您说new bessie.SuitableFood 时,编译器生成代码以查看实际的bessie对象并生成适当类型的新实例。 bessie.SuitableFood 是“路径相关类型”:导致最后一个标识符 (SuitableFood) 的“path”(bessie. 部分)实际上是该类型的一部分。这使您可以为同一类的每个单独对象拥有一个类型的自定义版本。


*嗯,实际上,我认为如果编译器更聪明一点,它可以推断出bessie.SuitableFood = Grass,因为bessie 是val,而不是var,因此不会t 改变它的类型。换句话说,编译器应该知道即使bessie 被声明为Animal,她实际上是Cow。也许编译器的未来版本会利用这些知识,也许有一个很好的理由说明这不是一个好主意,比我更专业的人会告诉我们。 (后记:刚刚做了一个!见下面特拉维斯布朗的评论。)

【讨论】:

  • 关于您的脚注:如果您在某事物上添加了类型注释,编译器会将其视为该类型,即使它可以推断出更具体的内容。如果您想跟踪类型成员而不是子类型,则需要使用像 val bessy: Animal { type SuitableFood = Grass } 这样的类型改进。
【解决方案2】:

关于你问题的第二部分:它没有。 Animal 没有指定它的食物是Food,而是Food 的某个子类型。编译器是否会接受这一点,像您的示例这样的代码会编译,并且错误地如此。编译器不知道必要的子类型是Grass(这就是为什么eat(new Grass) 也不起作用),它只知道有一些你的牛不能吃的食物并对此保持谨慎。

【讨论】:

    【解决方案3】:

    我相信bessy eat (new bessy.SuitableFood) 编译是一个错误(已在 2.11 中修复)。因为Animal 的另一个子类型可能有一个SuitableFood,而new 对此毫无意义,例如type SuitableFood = Food 甚至 type SuitableFood = Food with Int(Food with Int 是 Food 的完美子类型!)。

    【讨论】:

      猜你喜欢
      • 2014-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多