理解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的动物