There's a simple example in Programming in Scala by Odersky et al on abstract types, but it does not seem to follow to it's logical conclusion [now edited to make this my exact code]:
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)
}
They explain this will prevent me doing (as above):
val cow: Animal = new Cow
cow.eat(new FishFood)
So far so good. But the next natural step does not seem to work either:
cow.eat(new Grass)
I get a compile error:
type mistmatch;
found : Grass
required: Test.this.cow.Feed
cow.eat(new Grass)
^
But cow.Feed is Grass, so why doesn't this work?
The problem here is that your val cow is typed as Animal rather than Cow, so all that the compiler knows is that its eat method expects some specific subtype of Food, but it doesn't know which, and in particular it's unable to prove that that type is equal to Grass.
You can see the difference this makes to the type of the method (as viewed from Animal vs. as viewed from Cow) by asking for it's eta-expansion,
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>
You'll notice that in the second, more precisely typed, case the compiler views the method as taking an argument of type Grass rather than the abstract type cow.Feed.
And it should fail in such way - and actually, I think it is explained in Programming in Scala (2nd edition, p. 460).
On this line:
val cow: Animal = new Cow
You told the compiler to assume that cow could be any animal, including fish - and it certainly would do fish no good to eat grass!
If you would let the compiler to infer the proper type, it would compile:
val cow = new Cow
cow.eat(new Grass)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With