I was reading the section 20.7 of the book Programming in Scala and I was wondering why while this code compiles:
class Food
class Fish extends Food
class Grass extends Food
abstract class Animal {
type SuitableFood <: Food
def eat(food: SuitableFood)
}
class Cow extends Animal {
type SuitableFood = Grass
override def eat(food: Grass) {}
}
val bessy: Animal = new Cow
bessy eat (new bessy.SuitableFood)
This code does not (the rest of the code is the same as before, only the last line changes):
bessy eat (new Grass)
And as far as I understand the type of Grass is the same of Cow.SuitableFood.
Also, I have another question regarding this example:
If bessy is of type Animal, how can the compiler know that it needs a type SuitableFood -> Grass instead of a type Food? 'Cause trying to provide a new Food gives me a compile error of type mismatch, but the class Animal needs a type Food and the type of bessy is explicitly defined: Animal
It's because bessie
is declared Animal
rather than Cow
. bessie.SuitableFood
is a "path-dependent type" (see below).
Try this:
val clarabelle: Cow = new Cow
clarabelle eat (new Grass)
This works because the compiler can deduce that clarabelle.SuitableFood = Grass
from clarabelle
's declared type.
Since bessie
is declared Animal
, not Cow
, the compiler can't safely deduce that bessie.SuitableFood = Grass
.* When you say new bessie.SuitableFood
, the compiler generates code to look at the actual bessie
object and generate a new instance of the appropriate type. bessie.SuitableFood
is a "path-dependent type": the "path" (the bessie.
part) that leads to the last identifier (SuitableFood
) is actually part of the type. This enables you to have a custom version of a type for each individual object of the same class.
*Well, actually, I think that if the compiler were a little smarter, it could deduce that bessie.SuitableFood = Grass
, since bessie
is a val
, not a var
, and therefore won't change its type. In other words, the compiler ought to know that even though bessie
is declared Animal
, she's really a Cow
. Perhaps a future version of the compiler will make use of this knowledge, and perhaps there's a good reason why that wouldn't be a good idea, which someone more expert than I will tell us. (Postscript: One just did! See Travis Brown's comment below.)
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