13

Composition

Inheritance provides one mechanism for reusing code. An alternative mechanism supported by Object Orientated Programming is composition.

Inheritance is best used in cases where a class “is-a” instance of something else:

  • A circle is-a shape

  • A car is-a vehicle

  • A cat is-an animal

Composition, by comparison, is best used for modeling “has-a” relationships:

  • A circle has-a border

  • A car has-a door

  • A cat has-an owner

It is commonly said that composition should be favored over inheritance, especially in programming languages that only support single inheritance. I don’t believe this is necessarily true: inheritance should be used when modeling an “is-a” relationship, while composition should be used when modeling a “has-a” relationship. Generally you will come across more “has-a” cases than “is-a” cases, and therefore composition is generally more common.

Composition is a very simple subject in Java: any time an object encapsulates a field that refers to an object you are using composition. Typically composition is broken down into three sub-categories:

  • Composition: this refers to cases where the lifecycle of the composed object is implicitly linked to the lifecycle of the composing object. This is the case with the circle and the border: the lifecycle of the border is presumably linked to the lifecycle of the circle: if the circle is destroyed, the border will also be destroyed. Composition therefore implies ownership.

  • Aggregation: this refers to cases where there is a “has-a” relationship between two objects, but they can both exist independent of each other. For instance, a cat’s owner can still exists independent of the cat.

  • Association: this refers to cases where one object uses another object, but there is not a strong relationship between the two objects. As an example, a cat may use a cat door.

The term composition will refer to any one of these categories.

As an example, consider a case where you want to represent a color as three int values representing the ratio of red, green and blue in the color. The class will also capture the name for the color, and provide a method to return a hex encoded String for the color (as used by HTML/CSS). The Color class may look as follows:

package colors;

public class Color {

    private int red, green, blue;

    private String name;

    public Color(int red, int green, int blue, String name) {

        assert(red < 256 && red >= 0);

        assert(green < 256 && green >= 0);

        assert(blue < 256 && blue >= 0);

        this.red = red;

        this.green = green;

        this.blue = blue;

        this.name = name;

    }

    String getName() {

        return name;

    }

    public String getHexValue() {

        return "#"+getHexValue(red)+getHexValue(green)+

             getHexValue(blue).toUpperCase();

    }

    private String getHexValue(int intValue) {

        String s = Integer.toHexString(intValue);

        if (s.length() == 1) {

            return "0"+s;

        } else {

            return s;

        }

    }

}

This class introduces a number of new concepts you have not seen up until now. These are not implicitly linked to the concept of composition, but I will begin by discussing these.

The Color class declares three int fields. Where multiple fields are declared of the same type, the declaration can be performed in a single line:

private int red, green, blue;

This is the direct equivalent of declaring the fields on three separate lines. The only disadvantage with this approach is that it is not possible to initialize the fields to different values.

You will also notice that the getHexValue method takes advantage of a helper on the Integer class for converting a number into a hexadecimal String. In this particular case, I want to ensure that the hex value for each color is always two characters long, because this is the convention used by HTML, therefore I prepend a "0" if necessary.

Finally, notice that I have used the assert keyword in the constructor of Color to validate the numeric parameters are between 0 and 255 inclusive. This keyword provides a mechanism for asserting (or insisting) that a specific condition holds true. This is very useful for validating the arguments passed to a method.

If an assertion fails at runtime it will throw an AssertionError, which prevents the method or constructor from completing. It should be noted, however, that assertions are disabled by default at runtime: this means that by default Java will not check the assertion, and will not raise an exception.

You can specifically enable assertions at runtime by providing the VM argument -ea. It is typically to enable assertions during development, and disable them in production.

//

VM arguments are distinct from program arguments. Rather than providing values to the program, they provide information to the JVM telling it how to run the program. This may include options such as how much memory it needs to allocate.

Eclipse provides a separate input field for JVM arguments on the Arguments tab when “Run Configurations…” is selected.

Now that I have created a Color class, I can compose it within other classes; for instance, I may rewrite a Shape class as follows:

package colors;

 

public abstract class Shape {

    private Color fillColor;

    private Color lineColor;

    . . .

   

Each instance of a Shape now composes two instances of Color.

The beauty of composition is that once the Color class has been written and tested, it can be composed onto as many classes as we wish, and therefore all these classes benefit by reusing of the same code.

When designing and implemented classes, it is important to think about how they will be used by other classes, and design robust APIs that meet these needs. This ensures that your classes will be reusable by other code, and will prevent code duplication.

A Software Engineer Learns Java and Object Orientated Programming
titlepage.xhtml
part0000_split_000.html
part0000_split_001.html
part0000_split_002.html
part0000_split_003.html
part0000_split_004.html
part0000_split_005.html
part0000_split_006.html
part0000_split_007.html
part0000_split_008.html
part0000_split_009.html
part0000_split_010.html
part0000_split_011.html
part0000_split_012.html
part0000_split_013.html
part0000_split_014.html
part0000_split_015.html
part0000_split_016.html
part0000_split_017.html
part0000_split_018.html
part0000_split_019.html
part0000_split_020.html
part0000_split_021.html
part0000_split_022.html
part0000_split_023.html
part0000_split_024.html
part0000_split_025.html
part0000_split_026.html
part0000_split_027.html
part0000_split_028.html
part0000_split_029.html
part0000_split_030.html
part0000_split_031.html
part0000_split_032.html
part0000_split_033.html
part0000_split_034.html
part0000_split_035.html
part0000_split_036.html
part0000_split_037.html
part0000_split_038.html
part0000_split_039.html
part0000_split_040.html
part0000_split_041.html
part0000_split_042.html
part0000_split_043.html
part0000_split_044.html
part0000_split_045.html
part0000_split_046.html
part0000_split_047.html
part0000_split_048.html
part0000_split_049.html
part0000_split_050.html
part0000_split_051.html
part0000_split_052.html
part0000_split_053.html
part0000_split_054.html
part0000_split_055.html
part0000_split_056.html
part0000_split_057.html
part0000_split_058.html
part0000_split_059.html
part0000_split_060.html
part0000_split_061.html
part0000_split_062.html
part0000_split_063.html
part0000_split_064.html
part0000_split_065.html
part0000_split_066.html
part0000_split_067.html
part0000_split_068.html
part0000_split_069.html
part0000_split_070.html
part0000_split_071.html
part0000_split_072.html
part0000_split_073.html
part0000_split_074.html
part0000_split_075.html
part0000_split_076.html
part0000_split_077.html
part0000_split_078.html
part0000_split_079.html
part0000_split_080.html
part0000_split_081.html
part0000_split_082.html
part0000_split_083.html
part0000_split_084.html
part0000_split_085.html
part0000_split_086.html
part0000_split_087.html
part0000_split_088.html
part0000_split_089.html
part0000_split_090.html
part0000_split_091.html
part0000_split_092.html
part0000_split_093.html
part0000_split_094.html
part0000_split_095.html
part0000_split_096.html
part0000_split_097.html
part0000_split_098.html
part0000_split_099.html
part0000_split_100.html
part0000_split_101.html
part0000_split_102.html
part0000_split_103.html
part0000_split_104.html
part0000_split_105.html
part0000_split_106.html
part0000_split_107.html
part0000_split_108.html
part0000_split_109.html
part0000_split_110.html
part0000_split_111.html
part0000_split_112.html
part0000_split_113.html
part0000_split_114.html
part0000_split_115.html
part0000_split_116.html
part0000_split_117.html
part0000_split_118.html
part0000_split_119.html
part0000_split_120.html
part0000_split_121.html
part0000_split_122.html
part0000_split_123.html
part0000_split_124.html
part0000_split_125.html
part0000_split_126.html
part0000_split_127.html
part0000_split_128.html
part0000_split_129.html
part0000_split_130.html
part0000_split_131.html
part0000_split_132.html
part0000_split_133.html
part0000_split_134.html
part0000_split_135.html
part0000_split_136.html
part0000_split_137.html
part0000_split_138.html
part0000_split_139.html