Scala 类型:A 类不等于 T,其中 T 是:type T = A [英] Scala types: Class A is not equal to the T where T is: type T = A
问题描述
我正在阅读《Scala 编程》一书的第 20.7 节,我想知道为什么在编译这段代码时:
I was reading the section 20.7 of the book Programming in Scala and I was wondering why while this code compiles:
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)
这段代码没有(其余代码和之前一样,只是最后一行有变化):
This code does not (the rest of the code is the same as before, only the last line changes):
bessy eat (new Grass)
据我所知,Grass 的类型与 Cow.SuitableFood 相同.
And as far as I understand the type of Grass is the same of Cow.SuitableFood.
另外,我还有一个关于这个例子的问题:
Also, I have another question regarding this example:
如果 bessy 是 Animal 类型,编译器怎么知道它需要一个类型适合的食物 -> 草而不是食物类型?因为试图提供一个新的 Food 给我一个类型不匹配的编译错误,但是类 Animal 需要一个类型 Food 并且明确定义了 bessy 的类型:Animal
If bessy is of type Animal, how can the compiler know that it needs a type SuitableFood -> Grass instead of a type Food? 'Cause trying to provide a new Food gives me a compile error of type mismatch, but the class Animal needs a type Food and the type of bessy is explicitly defined: Animal
推荐答案
这是因为 bessie
被声明为 Animal
而不是 Cow
.bessie.SuitableFood
是路径依赖类型"(见下文).
It's because bessie
is declared Animal
rather than Cow
. bessie.SuitableFood
is a "path-dependent type" (see below).
试试这个:
val clarabelle: Cow = new Cow
clarabelle eat (new Grass)
这是可行的,因为编译器可以从clarabelle
的声明类型推导出clarabelle.SuitableFood = Grass
.
This works because the compiler can deduce that clarabelle.SuitableFood = Grass
from clarabelle
's declared type.
由于 bessie
被声明为 Animal
,而不是 Cow
,编译器不能安全地推断出 bessie.SuitableFood = Grass
.* 当您说 new bessie.SuitableFood
时,编译器生成代码以查看实际的 bessie
对象并生成适当类型的新实例.bessie.SuitableFood
是路径依赖类型":path"(bessie.
部分)指向最后一个标识符 (SuitableFood
) 实际上是类型的一部分.这使您可以为同一类的每个单独对象拥有一个自定义版本的类型.
Since bessie
is declared Animal
, not Cow
, the compiler can't safely deduce that bessie.SuitableFood = Grass
.* When you say new bessie.SuitableFood
, the compiler generates code to look at the actual bessie
object and generate a new instance of the appropriate type. bessie.SuitableFood
is a "path-dependent type": the "path" (the bessie.
part) that leads to the last identifier (SuitableFood
) is actually part of the type. This enables you to have a custom version of a type for each individual object of the same class.
*嗯,实际上,我认为如果编译器更聪明一点,它可以推断出 bessie.SuitableFood = Grass
,因为 bessie
是一个val
,不是 var
,因此不会改变它的类型.换句话说,编译器应该知道,即使 bessie
被声明为 Animal
,她也确实是一头 Cow
.也许编译器的未来版本将利用这些知识,也许有一个很好的理由为什么这不是一个好主意,比我更专业的人会告诉我们.(后记:刚刚做了!见下面 Travis Brown 的评论.)
*Well, actually, I think that if the compiler were a little smarter, it could deduce that bessie.SuitableFood = Grass
, since bessie
is a val
, not a var
, and therefore won't change its type. In other words, the compiler ought to know that even though bessie
is declared Animal
, she's really a Cow
. Perhaps a future version of the compiler will make use of this knowledge, and perhaps there's a good reason why that wouldn't be a good idea, which someone more expert than I will tell us. (Postscript: One just did! See Travis Brown's comment below.)
这篇关于Scala 类型:A 类不等于 T,其中 T 是:type T = A的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!