理解Scala对抽象类型和类的使用

理解Scala对抽象类型和类的使用,scala,abstract-type,Scala,Abstract Type,下一段代码不编译。为什么圣托林不能吃马粮龙卷风被宣布为一种新的马,马是动物的一个亚型,但它可以“吃”马粮 import scala.io.StdIn._ import util._ class Food abstract class Animal { type SuitableFood <: Food def eat(food: SuitableFood) } class Grass extends Food /*extends meaning should be

下一段代码不编译。为什么圣托林不能吃马粮
龙卷风
被宣布为一种新的
动物
的一个亚型,但它可以“吃”
马粮

import scala.io.StdIn._
import util._


class Food

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

class Grass extends Food  /*extends meaning should be "more specific than*/
class Fish extends Food
class HorseFood extends Grass

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

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

class Whale extends Animal
{
    type SuitableFood = Fish
    override def eat(food: SuitableFood) = {}

}

object abstractExample1 {

  def main(args: Array[String]) {

    val bessy: Animal = new Cow
    println("bessy = " + bessy)
    bessy eat (new Grass).asInstanceOf[bessy.SuitableFood]
     /*added this line because of a great answer someone posted for this questions but he deleted*/

    val willie: Animal = new Whale
    println("willie = " + willie)

    val santorin: Animal = new Horse
    println("santorin = " + santorin)

    val tornado = new Horse
    tornado eat new HorseFood

    print("tornado = " + tornado)
    santorin.eat(new HorseFood)

  }

}
导入scala.io.StdIn_
导入util_
等级食品
抽象类动物
{
适合食物的类型
动物#适合食物
食物

implicitly[Animal#SuitableFood <:< Food]
val santorin: Animal = new Horse
val santorin2: Animal = new Horse

implicitly[santorin.SuitableFood <:< Animal#SuitableFood]
implicitly[santorin2.SuitableFood <:< Animal#SuitableFood]
implicitly[santorin.SuitableFood =:= santorin2.SuitableFood] //-- fails
//                     ^^^^^^^                    ^^^^^^^
//                       these types are different
implicitly[santorin.SuitableFood =:= Grass] // -- fails

val tornado = new Horse
val tornado2 = new Horse

implicitly[tornado.SuitableFood =:= tornado2.SuitableFood] // compiles!
//                     ^^^^^^^                    ^^^^^^^
//                               Grass =:= Grass

implicitly[tornado.SuitableFood =:= Grass] // compiles
implicitly[HorseFood <:< Food]
implicitly[HorseFood <:< Grass]
implicitly[HorseFood <:< santorin.SuitableFood]//  -- fails
implicitly[HorseFood <:< Animal#SuitableFood]//  -- fails
圣托林:动物的
eat
方法签名如下:

def eat(food: santorin.SuitableFood) // SuitableFood is path-dependent
santorin.适配食品
食品
动物#适配食品

implicitly[Animal#SuitableFood <:< Food]
val santorin: Animal = new Horse
val santorin2: Animal = new Horse

implicitly[santorin.SuitableFood <:< Animal#SuitableFood]
implicitly[santorin2.SuitableFood <:< Animal#SuitableFood]
implicitly[santorin.SuitableFood =:= santorin2.SuitableFood] //-- fails
//                     ^^^^^^^                    ^^^^^^^
//                       these types are different
implicitly[santorin.SuitableFood =:= Grass] // -- fails

val tornado = new Horse
val tornado2 = new Horse

implicitly[tornado.SuitableFood =:= tornado2.SuitableFood] // compiles!
//                     ^^^^^^^                    ^^^^^^^
//                               Grass =:= Grass

implicitly[tornado.SuitableFood =:= Grass] // compiles
implicitly[HorseFood <:< Food]
implicitly[HorseFood <:< Grass]
implicitly[HorseFood <:< santorin.SuitableFood]//  -- fails
implicitly[HorseFood <:< Animal#SuitableFood]//  -- fails
HorseFood
Food
Grass
的亚型,但不是
santorin.SuitableFood
Animal#SuitableFood

implicitly[Animal#SuitableFood <:< Food]
val santorin: Animal = new Horse
val santorin2: Animal = new Horse

implicitly[santorin.SuitableFood <:< Animal#SuitableFood]
implicitly[santorin2.SuitableFood <:< Animal#SuitableFood]
implicitly[santorin.SuitableFood =:= santorin2.SuitableFood] //-- fails
//                     ^^^^^^^                    ^^^^^^^
//                       these types are different
implicitly[santorin.SuitableFood =:= Grass] // -- fails

val tornado = new Horse
val tornado2 = new Horse

implicitly[tornado.SuitableFood =:= tornado2.SuitableFood] // compiles!
//                     ^^^^^^^                    ^^^^^^^
//                               Grass =:= Grass

implicitly[tornado.SuitableFood =:= Grass] // compiles
implicitly[HorseFood <:< Food]
implicitly[HorseFood <:< Grass]
implicitly[HorseFood <:< santorin.SuitableFood]//  -- fails
implicitly[HorseFood <:< Animal#SuitableFood]//  -- fails
你应该读一下


你的类是不变的。这意味着
动物
适宜食物圣托林是
动物
而不是
,所以它“吃”类型而不是
马粮
。这是因为对它的引用是针对
动物
。
更改
val santorin:Animal=新马
到圣托林:马=新马

它会很好的工作

为什么你没有声明这个?-瓦尔·龙卷:动物=新的马我做了,而且龙卷再也不能吃马粮了。你能解释一下吗,瓦尔·威利:动物=新的鲸鱼?这只是我添加的一些代码来查看继承行为。我知道代码是如何编译的。这只是一些继承行为ed对我来说有点奇怪。如果你用逻辑术语而不是代码术语来思考,这更容易理解。在这里,你创建了一个新的马,但告诉编译器它是一个“动物”。因此它只期望“动物”的行为,而不是“马”。至于“龙卷风”,你没有显式地为它指定任何类型,所以scala隐式地提供了它创建对象的类类型,即Horse。我不确定我是否理解。泛型类可以是variant。普通非泛型类如何可以是variant或not?这是一个大致相似的示例,以便于清楚理解。当您使用类型为Anymal的对象时,编译器现在不知道什么类型是SuitableFood。而且,因为您的函数
eat
不是协变的,它只能接收精确类型SuitableFood(which未知)的参数。如果您将代码重写为泛型,那么很明显,带有SuitableFood的动物