Search code examples
scalageneric-variance

Class type parameters in Scala.


I'm having difficulty writing something that should be quite straight-forward, but I can't seem to get the syntax right.

I have a class hierarchy for foods:

Food :> Vegetable :> Bamboo

And for animals:

Animal :> Herbivore :> Panda

And I'm trying to define an eat method in Animal, so that Pandas can't eat Vegetables in general, only Bamboo. At the moment, my code looks like this:

class Food(val name : String)
class Vegetable(name: String) extends Food(name)
class Bamboo extends Vegetable("bamboo")

class Animal[F <: Food](val name : String) {
    def eat[T <: F](f : T) = println(s"$name eats some yummy ${f.name}")
}
class Herbivore[F <: Vegetable](name :String) extends Animal[Vegetable](name)
class Panda extends Herbivore[Bamboo]("panda")

my trouble is, that when I create a Vegetable, the Panda can eat it:

(new Panda) eat (new Vegetable("potato"))

So something's going wrong :(

Any help would be very welcome :)


Solution

  • You need to change:

    class Herbivore[F <: Vegetable](name :String) extends Animal[Vegetable](name)
    

    to:

    class Herbivore[F <: Vegetable](name :String) extends Animal[F](name)
    

    Otherwise you're throwing out the type information by not using F.