Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala类型:类A不等于T,其中T为:类型T=A_Scala_Types_Path Dependent Type - Fatal编程技术网

Scala类型:类A不等于T,其中T为:类型T=A

Scala类型:类A不等于T,其中T为:类型T=A,scala,types,path-dependent-type,Scala,Types,Path Dependent Type,我正在阅读《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 ov

我正在阅读《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属于动物类型,编译器如何知道它需要一种类型SuitableFood->Grass而不是一种类型Food?”因为试图提供一种新的食物给了我一个类型不匹配的编译错误,但是类Animal需要一种类型的食物,bessy的类型被明确定义:Animal

这是因为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
)的“”(bessie.部分)实际上是该类型的一部分。这使您能够为同一类的每个单独对象拥有类型的自定义版本



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

关于你问题的第二部分:没有
Animal
没有指定它的食物是
food
,而是
food
的某些子类型。编译器会接受这一点吗,就像你的例子会编译的代码一样,而且是错误的。编译器不知道必需的子类型是
Grass
(这就是
eat(newgrass)
也不起作用的原因),它只知道有些食物你的牛不能吃,并且对此很谨慎。

我相信
bessy eat(new bessy.SuitableFood)
编译是一个bug(在2.11中修复)。因为另一种
动物的子类型可能有
适合的食物
,而
新的
则毫无意义,例如
类型适合的食物=食物
,甚至
类型适合的食物=含Int的食物
含Int的食物是
食物
的完美子类型!).

关于您的脚注:如果您在某个对象上添加了类型注释,编译器会将其视为该类型,即使它可以推断出更具体的对象。如果希望跟踪类型成员而不是子类型,则需要使用类型细化,如
val bessy:Animal{type SuitableFood=Grass}
。建议:将标记路径依赖类型添加到此问题。这可能会吸引更了解这种困难的人来回答。(我自己仍在为路径依赖类型而挣扎。)@BenKovitz补充道,谢谢。
val clarabelle: Cow = new Cow

clarabelle eat (new Grass)