scala抽象类型

(通过一个例子来说明抽象类型的用法,假定你需要为动物的饮食习性建模, 你可能会定义如下的数据结构:


class Food
abstract class Animal {
    def eat(food: Food)
}
然后呢可能需要实现两个不同的实类对于与牛和草 Cows和Grass

class Grass extends Food
class Cow extends Animal {
    override def eat(food: Grass) {}
}

但是这段代码编译不通过:


<console>:13: error: class Cow needs to be abstract, since method eat in class Animal of type (food: Food)Unit is not defined
(Note that Food does not match Grass: class Grass is a subclass of class Food, but method parameter types must match exactly.)
       class Cow extends Animal {
             ^
<console>:14: error: method eat overrides nothing.
Note: the super classes of class Cow contain the following, non final members named eat:
def eat(food: Food): Unit
       override def eat(food: Grass) {}

怎么会出错呢,这是因为类 Cow 中的 eat 不能重载其父类,这是因为参数类型不一致,Animal 中 food 类型为 Food,而 Cow 中类型为 Grass。 仅管有人会说 Grass 是 Food 的子类,编译器没有必要这么严格。但是如果编译器允许这种情况存在,那么很快就出现新问题了:

假定前面的编译没有问题,我们在定义一个Fish类


class Fish extends Food
val bessy: Animal = new Cow
bessy eat (new Fish)

问题来了,我们给牛喂了鱼。如果前面的 Cow 可以编译通过的话,这段代码也是合法的[1],但结果却显然不对,因此编译器编译不通过 Cow 是有道理的。 对于这个问题,我们可以通过抽象类型来解决,哪种动物吃哪种食物由动物决定:



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

当定义新的 Animal 子类时,动物只能吃合适的食物,而 Animal 类本身不能决定那种食物合适,因此我们使用抽象类型定义。 但这个抽象类型有类型上界限制,表示 Animal 子类中使用的 SuitableFood 必须是 Food 的子类。

我们重新定义 Cow 如下:


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

你现在再试试喂鱼给牛看看:


scala> class Fish extends Food
defined class Fish

scala> val bessy :Animal = new Cow
bessy: Animal = Cow@a0992a

scala> bessy eat (new Fish)
<console>:14: error: type mismatch;
 found   : Fish
 required: bessy.SuitableFood
              bessy eat (new Fish)
                         ^
注释1:

When you assign bessy, you upcast the Cow instance to an Anmial:

val bessy: Animal = new Cow

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值