lukens
lukens

Reputation: 489

Java generics overriding method

I'm new to using generics (very late to the party, I know), and aren't sure if what I am trying to achieve is possible, and if so, how.

OK, this is a contrived example of what I am try to achieve, that hopefully shows the pattern without any clutter:

// Pet and Cats
interface Pet { }
interface Cat extends Pet { }
class TabbyCat implements Cat { }

// Pet food and cat food
interface PetFood<T extends Pet> { }
interface CatFood extends PetFood<Cat> {}
class DryCatFood implements CatFood {}
class WetCatFood implements CatFood {}

// PetBowl
interface PetBowl<T extends Pet> {
    public void addFood(PetFood<T> food);
}

// CatBowl
class CatBowl implements PetBowl<Cat> {

    // this doesn't override method, why not?
    public void addFood(CatFood food) { }

    // this does
    public void addFood(PetFood<Cat> food) { }

}

So, basically what I am trying to do is make CatBowl implement PetBowl, but so that the addFood() method only allows CatFood to be added.

The only solution I have been able to come up with is:

...

// PetBowl
interface PetBowl<T extends Pet, F extends PetFood<T>> {
    public void addFood(F food);
}

// CatBowl
class CatBowl implements PetBowl<Cat, CatFood> {

    public void addFood(CatFood food) { }

}

However, in my non-contrived case there are more parameters, and this ends up making for a lot of boilerplate all over the place, so I'm hoping for a "neater" solution.

Upvotes: 1

Views: 205

Answers (2)

megakorre
megakorre

Reputation: 2223

Yes, the promise of the interface is that it can take a PetFood<Cat> so if you where able to make it take CatFood then you would limit the types the that your class can take ... and break the "interface".

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 692121

This is not really linked to generics. The interface PetBowl<Cat> has a method addFood(PetFood<Cat> food). So, any class implementing this interface should have such a method. addFood(CatFood food) is not acceptable because it doesn't allow adding any kind of PetFoo<Cat>, but only CatFood.

It's the same as if you had

interface A {
    void add(Object o);
}

class AImpl implements A {
    public void add(String s);
}

Obviously, AImpl.add doesn't override A.add, because it only accepts Strings, and not Objects.

Upvotes: 3

Related Questions