Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Handle Composition/Aggregation and Polymorphism in Java

Tags:

java

oop

I have two abstract classes, lets call them Car's and Wheel's. I am handling different types of cars using some inheritance. So lets say there are two derivations MonsterTruckCar and ToyCar. Additionally there are different types of wheels that correspond to the Cars, say TreadedWheel's and PlasticWheel's (the mapping does not necessarily need to be one-to-one from types of cars to types of wheels). Further Car's are composed of Wheel's.

The way I thought I would be able to do this in Java is by using an attribute of Car's to be type ArrayList<Wheel>. The issue I am having is that now when I want to use polymorphism on the Wheel's I cannot because whenever I deal with a Wheel it is through an ArrayList which is not a derived class of Wheel's.

I thought I might be able to use bounded wildcards, or just a lot of switch statements to handle different combinations but I dont think either of those would be the greatest solutions. How can I handle such a structure?

Further, how do you add Wheel's to the composition/collection in Car's. That is, I need to be able to add a variable amount of concrete Wheel's to a Car, further this is going to be based off of some user input. so I would like to have a while loop in the default constructor that prompt the user if he/she wants to add another wheel and then if he/she does I add another Wheel to whatever is aggregating/collecting them in Car's.

Edit: Edited the names of the classes themselves from plural (Wheels) to singular with a 's (Wheel's) to clarify the relationship. Added the last paragraph which explains further the behavior I am looking for.

like image 577
Jordan Avatar asked Oct 26 '11 02:10

Jordan


1 Answers

Add a generic parameter to your Car class that specified the wheel type. Here's a very basic implementation you can build on:

Edited:

Includes updated requirements, which is tricky, but doable...

public interface Wheel {
    void setSize(int diameter);
}

public static abstract class Car<T extends Wheel> {

    private List<T> wheels = new ArrayList<T>();

    protected Car(int numberOfWheels, Class<T> wheelClass) {
        while (wheels.size() < numberOfWheels) {
            T wheel;
            try {
                wheel = wheelClass.newInstance();
            } catch (Exception e) {
                throw new RuntimeException(e); // simplified exception handling
            }
            wheel.setSize(5); // Ask user for wheel details etc
            wheels.add(wheel);
        }
    }

    public List<T> getWheels() {
        return wheels;
    }
}

public static class PlasticWheel implements Wheel { // or extends Wheel
    @Override
    public void setSize(int diameter) {
    }
}

public static class ToyCar extends Car<PlasticWheel> {
    public ToyCar() {
        super(6, PlasticWheel.class); // or you could pass number of wheels in to this constructor
    }
}

public static class TreadedWheel implements Wheel { // or extends Wheel

    @Override
    public void setSize(int diameter) {
    }
}

public static class MonsterTruckCar extends Car<TreadedWheel> {
    public MonsterTruckCar() {
        super(4, TreadedWheel.class); // or you could pass number of wheels in to this constructor
    }
}
like image 107
Bohemian Avatar answered Sep 21 '22 20:09

Bohemian