Search code examples
javaarraylistpolymorphismcovariancecontravariance

How to use polymorphism in ArrayLists?


So I have this zoo program where I want to have a list of rooms in a zoo, and a list of cats in each room.

I have 3 classes: Felid, Housecat and Wildcat - Housecat and Wildcat extend Felid. depending on the literal class of animal (right now I have tiger, persian, siamese and cheetah - tiger and cheetah extend wildcat, persian and siamese extend housecat) certain attributes will be automatically assigned.

Class diagram - https://i.sstatic.net/oDydn.jpg

For example these are the fields for felid:

String speciesName;
String furColour;
String gender;
int weightPounds;
boolean packAnimal;
String habitat;
int age;

These are the fields for housecat:

String ownerName;
String catName;
boolean feral;

These are the fields for wildcat:

boolean manEater;

In my constructor for housecat I have

    if(catName == null || catName.equals("")){
        feral = true;
    } 

and if the cat's feral, when the user creates a HouseCat with a cat name and uses 'printCatInfo()':

@Override
public void printCatInfo(){
    if(feral){
        System.out.println("feral" + "\n" + speciesName + "\n" + furColour + "\n" + gender + 
            "\n" + weightPounds + "lbs\n" + "is not a pack animal" + "\n" + habitat + "\n" + age + " years old (human)");
    }
    else{
        System.out.println("owner name is: " + ownerName + "\n" + "cat name is: " + catName + "\n" + speciesName + "\n" + furColour + "\n" + gender + 
            "\n" + weightPounds + "lbs\n" + "is not a pack animal" + "\n" + habitat + "\n" + age + " years old (human)" + "\n");
    }     
}

It won't print its name.

feral
siamese
White or grey abdomen with black legs, face and tail
male
8lbs
is not a pack animal
urban
7 years old (human)

The trouble is that it counted all cats as feral which I assumed was because the list I used for the list of cats is:

ArrayList<Felid> catList = new ArrayList<Felid>();

So I guess the catName will always be null because the housecats that are added to the list will just count as type 'felid'.

How do I create a list that I can throw all of the cats into and but still treat them as their respective classes?

edit: thanks for pointing out the assignment operator error, it's still only printing feral though

Final edit: Thank you very much to 'DoubleDouble' for pointing out how to use 'Super()' to me - that's not what I expected the problem was. This was the problem:

public class Siamese extends HouseCat{
    public Siamese(int weightPounds, int age, String ownerName, String catName, String gender){
        this.speciesName = "siamese";
        this.furColour = "White or grey abdomen with black legs, face and tail";        
        this.ownerName = ownerName;
        this.catName = catName;
        this.weightPounds = weightPounds;
        this.age = age;
        this.gender = gender;
    }
}

New code:

public class Siamese extends HouseCat{
    public Siamese(int weightPounds, int age, String ownerName, String catName, String gender){
        super(catName);
        this.speciesName = "siamese";
        this.furColour = "White or grey abdomen with black legs, face and tail";        
        this.ownerName = ownerName;
        this.catName = catName;
        this.weightPounds = weightPounds;
        this.age = age;
        this.gender = gender;
    }
}

Solution

  • Your constructors seem to the following (correct me if I am wrong):

    public Siamese(int weightPounds, int age, String ownerName, String catName, String gender)
    {
        this.weightPounds = weightPounds;
        this.age = age;
        this.ownerName = ownerName;
        this.catName = catName;
        this.gender = gender;
    }
    
    public HouseCat()
    {
        if(catName == null || catName.equals(""))
        {
            feral = true;
        }
    }
    

    Since ownerName, catName, and feral are all a part of the HouseCat class, it is best to let the HouseCat constructor handle those fields.

    public HouseCat(String ownerName, String catName)
    {
        this.ownerName = ownerName;
        this.catName = catName;
        if(catName == null || catName.equals(""))
        {
            feral = true;
        }
    }
    

    Siamese looks like this then:

    public Siamese(int weightPounds, int age, String ownerName, String catName, String gender)
    {
        super(ownerName, catName);
        this.weightPounds = weightPounds;
        this.age = age;
        this.gender = gender;
    }