In studying Java development, the HasA and IsA relationships came up in the coursework. Is-A relationships are forms of inheritance. A car is a vehicle. So a vehicle is the base class and car would inherit from it. Alternatively, a table has a top, legs, maybe some drawers. This is an example of composition.

Code: Inheritance

Suppose in an inheritance example we model a building as the base class:

public class Building {

    private int walls;
    private int height;
    private int squareFeet;
    private int numberOfDoors;
    private boolean skylight;
    private String flooringMaterial;

    public Building(int walls, int height, int squareFeet, int numberOfDoors, boolean skylight, String flooringMaterial) {
        this.walls = walls;
        this.height = height;
        this.squareFeet = squareFeet;
        this.numberOfDoors = numberOfDoors;
        this.skylight = skylight;
        this.flooringMaterial = flooringMaterial;
    }

As there are many types of buildings, each would extend from this (inherit) base class. For example, a condo Is-A building and could be defined like so:

public class Condo extends Building {

    private boolean hoa;
    private boolean sharedWall;
    private int numberOfBedrooms;
    private int numberOfBathrooms;

    public Condo(int walls, int height, int squareFeet, int numberOfDoors, boolean skylight, String flooringMaterial,
                 boolean hoa, boolean sharedWall, int numberOfBathrooms, int numberOfBedrooms) {
        super(walls, height, squareFeet, numberOfDoors, skylight, flooringMaterial);
        this.hoa = hoa;
        this.sharedWall = sharedWall;
        this.numberOfBathrooms = numberOfBathrooms;
        this.numberOfBedrooms = numberOfBedrooms;
    }

Code: Composition

Conversely, in composition, a relationship between code is specified in a Has-A relationship. Going back to the table analogy:

public class TableTop {
    private String color;
    private String material;
    private Drawer drawer;  // Composition, not inheritance.

    public TableTop(String color, String material, Drawer drawer) {
        this.color = color;
        this.material = material;
        this.drawer = drawer;
    }

    public String getColor() {
        System.out.println("tabletop color: " + color);
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getMaterial() {
        System.out.println("tabletop material: "+ material);
        return material;
    }

    public void setMaterial(String material) {
        this.material = material;
    }

    public Drawer getDrawer() {
        return drawer;
    }

    public void setDrawer(Drawer drawer) {
        this.drawer = drawer;
    }
}

In the above, our TableTop class references another class called Drawer, so our table top might have a drawer hooked to the underside. I could also have chosen to use Legs… or something else.

The other class is defined:

public class Drawer {

    private boolean sliding;
    private int numberOfDrawers;

    public Drawer(boolean sliding, int numberOfDrawers) {
        this.sliding = sliding;
        this.numberOfDrawers = numberOfDrawers;
    }

    public boolean isSliding() {
        System.out.println("drawer sliding?: "+ sliding);
        return sliding;
    }

    public void setSliding(boolean sliding) {
        this.sliding = sliding;
    }

    public int getNumberOfDrawers() {
        System.out.println("drawer number of: "+ numberOfDrawers);
        return numberOfDrawers;
    }

    public void setNumberOfDrawers(int numberOfDrawers) {
        this.numberOfDrawers = numberOfDrawers;
    }
}

The table also has a Legs class:

public class Leg {

    private int length;
    private String material;
    private Foot foot;

    public Leg(int length, String material, Foot foot) {
        this.length = length;
        this.material = material;
        this.foot = foot;
    }

    public int getLength() {
        System.out.println("leg length: "+ length);
        return length;
    }

    public void setLength(int length) {
        this.length = length;
    }

    public String getMaterial() {
        System.out.println("leg material: " + material);
        return material;
    }

    public void setMaterial(String material) {
        this.material = material;
    }

    public Foot getFoot() {
        return foot;
    }

    public void setFoot(Foot foot) {
        this.foot = foot;
    }
}

Each leg has a foot, and that foot can be made of specific material, using a design pattern, and a color:

public class Foot {
    private String color;
    private String material;
    private int designPattern;

    public Foot(String color, String material, int designPattern) {
        this.color = color;
        this.material = material;
        this.designPattern = designPattern;
    }

    public String getColor() {
        System.out.println("foot color: "+color);
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String getMaterial() {
        System.out.println("foot material: " + material);
        return material;
    }

    public void setMaterial(String material) {
        this.material = material;
    }

    public int getDesignPattern() {
        System.out.println("foot pattern: "+designPattern);
        return designPattern;
    }

    public void setDesignPattern(int designPattern) {
        this.designPattern = designPattern;
    }
}

After each part of the composition is created, then they are assembled into an object (in this case a table) like so:

public class Table {
    private TableTop tableTop;
    private Leg leg;

    public Table(TableTop tableTop, Leg leg) {
        this.tableTop = tableTop;
        this.leg = leg;

    }

    public void details() {
        tableTop.getColor();
        tableTop.getDrawer().getNumberOfDrawers();
        tableTop.getDrawer().isSliding();
        tableTop.getMaterial();
        leg.getLength();
        leg.getMaterial();
        leg.getFoot().getColor();
        leg.getFoot().getDesignPattern();
        leg.getFoot().getMaterial();
    }
    public TableTop getTableTop() {
        return tableTop;
    }

    public Leg getLeg() {
        System.out.println(leg);
        return leg;
    }
}

Instantiating the object is handled in each of the elements like so:

        TableTop theTableTop = new TableTop("redwood", "pressed wood", new Drawer(true, 1));
        Leg theLeg = new Leg(36, "pressed wood", new Foot("brass", "brass", 22));

        Table theTable = new Table(theTableTop, theLeg);
        theTable.details();

Which would output something like:

tabletop color: redwood
drawer number of: 1
drawer sliding?: true
tabletop material: pressed wood
leg length: 36
leg material: pressed wood
foot color: brass
foot pattern: 22
foot material: brass

Aggregation

A third type of OO methodology of code sharing is that of Aggregation. As described on this StackOverflow answer, aggregation is a Has-An type relationship.

The difference between a Has-A and Has-An is that the Has-A relationship is required. A table needs legs. The composition above assumes a requirement of each component. A house has walls, and walls are required.

A Has-An relationship is similar to Has-A, but one or more elements is not required. A car has a wheel(s), but it has an driver. The driver is not required for there to be a car.

Leave a Reply

Your email address will not be published. Required fields are marked *