2

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 :)

ehrt1974
  • 1,166
  • 2
  • 11
  • 24

1 Answers1

8

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.

Matt Fowler
  • 2,563
  • 2
  • 15
  • 18
  • Many thanks :) that fixes the panda.eat(potato) problem. Now I have the problem, that a (new Herbivore("cow")).eat(new Bamboo) doesn't compile :( ---- sorry, i shouldn't call it a cow, let's call it new Herbivore("generic herbivore") – ehrt1974 Mar 21 '17 at 16:17
  • 1
    @ehrt1974 `new Herbivore[Vegetable]("generic herbivore").eat(new Bamboo)` – nmat Mar 21 '17 at 16:58
  • I also don't think it makes sense for `Animal` and `Herbivore` to be non abstract classes. – Jasper-M Mar 21 '17 at 18:13