I'm having trouble changing the type parameter of an inherited method.
abstract class Animal {
abstract List<Animal> animalList();
}
public class Dog extends Animal {
@Override
public List<Dog> animalList() {
...
...
}
}
public class Cat extends Animal {
@Override
public List<Cat> animalList() {
...
...
}
}
All animal subclasses need to implement a method animalList
. What's the best practice of doing this if i want the best possible code regarding readability and maintainability? Please note that this is extremely simplified i comparison to the actual project.
CodePudding user response:
I don't know what the best solution is, but I would do the following:
import java.util.List;
abstract class Animal {
abstract <T extends Animal> List<T> animalList();
}
...
import java.util.List;
public class Dog extends Animal {
@Override
List<Dog> animalList() {
return null;
}
}
...
import java.util.List;
public class Cat extends Animal{
@Override
List<Cat> animalList() {
return null;
}
}
CodePudding user response:
It feels a little bit weird, but this might work.
abstract class Animal<T extends Animal<T>> {
abstract List<T> animalList();
}
class Dog extends Animal<Dog> {
@Override
List<Dog> animalList() {
}
}
class Cat extends Animal<Cat> {
@Override
List<Cat> animalList() {
}
}
CodePudding user response:
Though the working solutions are already provided, I'll put some useful references that might be helpful.
The reason why you cannot "return dogs or cats as animals" is that they are wrapped in a collection (java.util.List
in this case).
F.e. you CAN write this way:
abstract class Animal {
abstract Animal[] animalArray();
}
public class Dog extends Animal {
@Override
public Dog[] animalArray() {
//
}
}
public class Cat extends Animal {
@Override
public Cat[] animalArray() {
//
}
}
Why can't you do the same for List
s?
Because in Java arrays are covariant, but generics (Collection<E>
) are invariant.
There is a great explanation on this topic in the best Java book, I've read - "Effective Java" (now there is a 3rd edition) by J. Bloch (Item 28: Prefer Lists to Arrays).
The good working solution is provided by @Zymus, using the trick so-called "recursive type bound", which is also described in the book (Item 30: Favor Generic Methods).