Java inheritance vs. composition: How to choose

Compare inheritance and composition, the two fundamental ways to relate Java classes, then practice debugging ClassCastExceptions in Java inheritance.

1 2 Page 2
Page 2 of 2

public class InheritanceCompositionChallenge {
    private static int result;
    public static void main(String... doYourBest) {
        Character homer = new Homer();
        homer.drink();
        new Character().drink();
        ((Homer)homer).strangleBart();
        Character character = new Character();
        System.out.println(result);
        ((Homer)character).strangleBart();
    }
    static class Character {
        Character() {
            result++;
        }
        void drink() {
            System.out.println("Drink");
        }
    }
    static class Homer extends Character {
        Lung lung = new Lung();
        void strangleBart() {
            System.out.println("Why you little!");
        }
        void drink() {
            System.out.println("Drink beer");
            lung.damageLungs();
        }
    }
    static class Lung {
        void damageLungs() {
            System.out.println("Soon you will need a transplant");
        }
    }
}

Which is the output after running the main method?

A)


Drink
Drink
Why you little!
2
Exception in thread "main" java.lang.ClassCastException:....

B)


Drink beer
Soon you will need a transplant
Drink
Why you little!
Exception in thread "main" java.lang.ClassCastException:....

C)


Drink beer
Soon you will need a transplant
Drink
Why you little!
3
Exception in thread "main" java.lang.ClassCastException:....

D)


Drink beer
Soon you will need a transplant
Drink
Why you little!
2
Why you little!

What just happened?

The correct output from the inheritance challenge is C:


Drink beer
Soon you will need a transplant
Drink
Why you little!
3
Exception in thread "main" java.lang.ClassCastException:....

To understand why, simply examine the code, starting from the top:


Character homer = new Homer();
 homer.drink();

Since we instantiate the object with Homer, the Homer method implementation will be executed, producing the following output:


Drink beer
Soon you will need a transplant

Then, we invoke the drink() method directly from the Character class.


new Character().drink();

We will have the following output:


Drink beer

At this line we use casting and invoke the strangleBart() method normally:


 ((Homer)homer).strangleBart();

Then we ask for the resulting output:


System.out.println(result);

Since we know the super constructor always has to be invoked, we just have to count how many times Character or Homer was instantiated. Now we know the output will be 3

Finally, we try to invoke a method from a misused casting:


((Homer) character).strangleBart();

We tried to convert the class type and implementation of Character, so a ClassCastException will be thrown. (This is because there is no Homer information in the Character class.)

Video challenge! Debugging the Java inheritance example

Debugging is one of the easiest ways to fully absorb programming concepts while also improving your code. In this video you can follow along while I debug and explain the Java inheritance challenge.

Common mistakes with inheritance

  • Writing inheritance code before thinking it through carefully.
  • Using inheritance when composition is a better option.
  • Not taking advantage of polymorphism when using inheritance.
  • Using inheritance when the "is a" test doesn't pass.

What to remember about Java inheritance

  • When instantiating a superclass with the subclass, the subclass instantiation will be considered.
  • In order to decide whether to use inheritance, ask yourself whether the child class really is a specialized type of the parent (the "is a" test).
  • The super reserved word will be added automatically in your constructor if you don't declare it yourself.
  • If you have the parent class type and the instantiation of the subclass for this type, you may cast it to the subclass.
  • If the superclass has a constructor receiving at least one parameter, you must invoke this super constructor in the subclass passing the required parameter.

Learn more about Java

This story, "Java inheritance vs. composition: How to choose" was originally published by JavaWorld.

Copyright © 2020 IDG Communications, Inc.

1 2 Page 2
Page 2 of 2
InfoWorld Technology of the Year Awards 2023. Now open for entries!