方法参数中的抽象类型

ent*_*ave 3 generics types scala abstract-type

在Odersky等人的Scala编程中有一个关于抽象类型的简单例子,但它似乎没有遵循它的逻辑结论[现在编辑使我的确切代码]:

class Food
class Grass extends Food
class FishFood extends Food

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

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

class Test extends App {
  val cow: Animal = new Cow
  cow.eat(new FishFood)
  cow.eat(new Grass)
}
Run Code Online (Sandbox Code Playgroud)

他们解释说这会阻止我做(如上所述):

val cow: Animal = new Cow
cow.eat(new FishFood)
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.但下一个自然步骤似乎也不起作用:

cow.eat(new Grass)
Run Code Online (Sandbox Code Playgroud)

我收到编译错误:

type mistmatch;
found : Grass
required: Test.this.cow.Feed
 cow.eat(new Grass)
         ^
Run Code Online (Sandbox Code Playgroud)

但是牛.饲料是草,所以为什么这不起作用?

Mil*_*bin 8

这里的问题是你的val cow被输入Animal而不是Cow,所以编译器知道的是它的eat方法需要一些特定的子类型Food,但它不知道哪个,特别是它无法证明该类型等于Grass.

通过询问它的eta扩展,你可以看到它对方法类型的不同(从Animal查看中看到的Cow).

scala> val cow: Animal = new Cow
cow: Animal = Cow@13c02dc4

scala> cow.eat _
res12: cow.Feed => Unit = <function1>

scala> cow.asInstanceOf[Cow].eat _
res13: Grass => Unit = <function1>
Run Code Online (Sandbox Code Playgroud)

您会注意到,在第二种更精确类型的情况下,编译器将该方法视为采用类型的参数Grass而不是抽象类型cow.Feed.