Scala 类型:A 类不等于 T,其中 T 是:type T = A [英] Scala types: Class A is not equal to the T where T is: type T = A

查看:67
本文介绍了Scala 类型:A 类不等于 T,其中 T 是: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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆