I have a question on applying polymorphism: Let's assume I have a class Bird
, and I have many classes that extend it (like Pigeon
, Falcon
and so on).
Next, I have a Cage
class. In this class, I want to make a list of birds which live in that cage (only one kind of bird can live in each cage).
Because of that, I do not know the extended type of the list (A Pigeon
? Or maybe an Eagle
?), the only thing i know is that it will be a Bird
.
If Pigeon extends Bird
Using polymorphism I can declare a bird as:
Bird tom = new Pigeon();
instead of Pigeon tom = new Pigeon();
So why I can't initialize something like that in the constructor: [...]
private List<Bird> birdList;
public Cage() {
this.birdList = new ArrayList<Pigeon>();
/* Instead of birdList = new ArrayList<Bird>(); */
}
If you cannot do that, is it possible to achieve my goal in another way?
What you probably want is to use a generic type for your Cage to capture the exact kind of bird that lives in the cage. Like this:
import java.util.ArrayList;
import java.util.List;
public class Cage<T extends Bird> {
private List<T> birdList;
public Cage() {
birdList = new ArrayList<T>();
}
public void addBird(T bird) {
birdList.add(bird);
}
}
You would then use the cage like this:
Cage<Eagle> eagleCage = new Cage<Eagle>();
eagleCage.addBird(new Eagle());
The reason you can't do List<Bird> birdList = new ArrayList<Pidgeon>()
is because then someone could use the birdList
reference to write any Bird
subclass to your ArrayList<Pidgin>
. This must not be allowed by the type checker, a list of Pidgin
must contain only Pidgin
instances.
Arne gives one solution using a type parameter on Cage
. If this is not what to want to do you can declare birdList
with a wildcard type.
Your example would look like this:
class Bird {}
class Pidgeon extends Bird {}
class Cage {
// This is a wildcard type and can contain lists of any
// subtype to Bird, but you can't add elements to it.
private List<? extends Bird> birdList;
public Cage() {
this.birdList = new ArrayList<Pidgeon>();
}
}
An upper bounded wildcard type like this tells the compiler birdList
contains a list of some unknown subclass to Bird
. This has the effect that you can not add any elements to the list since you can not be sure to add the right subtype, and when you read from the list you will get references of type Bird
.
Since in each cage live only one kind of bird, you can use Generic Types to type your Cage class.
For example, Cage<T>
will define a list of bird this way : List<T> birdList
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With