Gabriele Gabriele - 12 days ago 5
Java Question

Specializing method arguments in subclasses in Java

Consider the following situation:

public abstract class AnimalFeed{
}
public class FishFeed extends AnimalFeed{
}
public class BirdFeed extends AnimalFeed{
}

public abstract class Animal{

public void eat(AnimalFeed somethingToEat)

}


Now I would like to define a class "Bird" extending "Animal" being sure that when the bird eats, it eats only BirdFeed.

One solution would be to specify a sort of contract, in which the caller of "eat" must pass an instance of the appropriate feed

public class Bird extends Animal{

@Override
public void eat(AnimalFeed somethingToEat){

BirdFeed somethingGoodForABird

if(somethingToEat.instanceOf(BirdFeed)){
somethingGoodForABird = (BirdFeed) somethingGoodForABird
}else{
//throws error, complaining the caller didn't feed the bird properly
}
}
}


Is it acceptable to delegate the responsibility of the parameter to the caller? How to force the caller to pass a specialization of the parameter? Are there alternative design solutions?

Answer

You'd need to add a type variable to the class:

public abstract class Animal<F extends AnimalFeed> {
  public abstract void eat(F somethingToEat);
}

Then you can declare your subclasses as wanting a particular type of AnimalFeed:

public class Bird extends Animal<BirdFeed> {
  public void eat(BirdFeed somethingToEat) {}
}

public class Fish extends Animal<FishFeed> {
  public void eat(FishFeed somethingToEat) {}
}