Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possibile to super-cast a List?

Tags:

java

list

casting

This might sound a little bit trivial, but I'm really not able to find the crux of the matter.

List<Dog> dogs = getListOfDogs();
List<Cat> cats = getListOfCats();

feed(dogs);
feed(cats);

public void feed(List<Animal> animals) {
    // feed the animal:
    // depending on the type of animal, I might want to give it
    // different kind of food.
}

class Dog implements Animal { /**/ }
class Cat implements Animal { /**/ }
interface Animal { /**/ }

I'm in a context very similar to the one depicted above. Let's also suppose that getListOfDogs and getListOfCats are fixed, and there's no way to act on that side.

Of course, as put in that way, it's an illegal code: feed accepts only List<Animal> types, while I can only have List<Cat> and List<Dog>.

Since feed is a function that is almost identical for the two animals, with the exception of the kind of food (and I can manage it via instanceof), I would like to avoid copying it, just changing the signatures.

Is there any way to super-cast the two lists? Something like this (that is obviously incorrect): feed((List<Animal>) getListOfDogs());

like image 574
Gian Segato Avatar asked Jan 21 '26 15:01

Gian Segato


2 Answers

What you're looking for is:

public void feed(List<? extends Animal> animals) {

This will accept a List<Animal>, or a List<Dog>, or a List<Cat>, or so on. You won't be able to add anything to animals, since it could be any type of list. If you access an item in animals you'll get back a reference of type Animal.

like image 99
user253751 Avatar answered Jan 23 '26 03:01

user253751


You can do what you've said you want, by declaring feed like this:

public void feed(List<? extends Animal> animals)

However, you may well not want to do that, because of your subsequent statement:

Since feed is a function that is almost identical for the two animals, with the exception of the kind of food (and I can manage it via instanceof)...

Don't reach for instanceof lightly, it's usually the wrong tool. Instead, parameterize feed:

private void feed(List<? extends Animal> animals, Food food)

...and then

public void feed(List<Dog> animals) {
    this.feed(animals, this.dogFood);
}

and

public void feed(List<Cat> animals) {
    this.feed(animals, this.catFood);
}

...or similar.

like image 33
T.J. Crowder Avatar answered Jan 23 '26 05:01

T.J. Crowder