【问题标题】:abstract type in scalascala中的抽象类型
【发布时间】:2013-11-19 11:59:54
【问题描述】:

我只是在Scala 中处理抽象类型,我得到了一个错误

我正在尝试的示例:

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

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

scala> class Fish extends Food
defined class Fish

scala> val bessy: Animal = new Cow
bessy: Animal = Cow@5c404da8

scala> bessy.eat(new bessy.SuitableFood)
<console>:13: error: class type required but bessy.SuitableFood found
              bessy.eat(new bessy.SuitableFood)
                                  ^

scala> bessy.eat(bessy.SuitableFood)
<console>:13: error: value SuitableFood is not a member of Animal
              bessy.eat(bessy.SuitableFood)

scala> bessy.eat(new Grass)
<console>:13: error: type mismatch;
 found   : Grass
 required: bessy.SuitableFood
              bessy.eat(new Grass)

这些错误是什么?

为什么我不能将new Grass 作为参数传递给eat 方法,而当我创建一个像这样的对象时

scala> val c=new Cow
c: Cow = Cow@645dd660


scala> c.eat(new Grass)

你能给我一些想法吗?

【问题讨论】:

    标签: scala abstract path-dependent-type


    【解决方案1】:

    当您分配bessy 时,您将Cow 实例向上转换为Anmial

    val bessy: Animal = new Cow
    

    所以从静态的角度来看,bessy 是一个Animal,因此是bessy.SuitableFood 抽象。现在到错误:

    1. 您不能使用new 创建抽象类型的对象。
    2. bessy.SuitableFood 尝试访问值成员 SuitableFood(即 def/val)
    3. 由于bessy 是“唯一”一个Animal,你不知道(静态地)它是否可以吃Grass

    你可以做的是向Animal添加一个方法,让你可以创建食物:

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

    并实施:

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

    现在您可以致电(在任何Animal):

    bessy.eat(bessy.makeFood())
    

    【讨论】:

    • +1 我的答案几乎完全相同。从你第一次删除。
    • 对不起,还是不明白。牛的适合食物被覆盖为草,所以新的 bessy.SuitableFood 是新的草。它和你在 makeFood 中写的一样。唯一的区别是你将它包装在一个方法中......那么为什么不能编译 bessy.eat(new bessy.SuitableFood)
    • 因为new 调用的目标类必须在编译时静态已知。通过将new 调用放入Cow 的范围内,我们就实现了这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-01
    • 2011-12-27
    • 1970-01-01
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多