Amumu
Amumu

Reputation: 18552

Inheritance vs Composition?

I asked similar question one month ago: Inheritance though composition?

I took the examples from this article: http://www.javaworld.com/javaworld/jw-11-1998/jw-11-techniques.html?page=1 However, this time is a different problem. Sorry for posting a lot of codes, but it is just long, it's not difficult to read.

class Fruit {
    public int peel() {

            System.out.println("Peeling is appealing.");
            return 1;
        }
    }

class Apple extends Fruit {
}

class Example1 {

    public static void main(String[] args) {

        Apple apple = new Apple();
        int pieces = apple.peel();
    }
}

After modification, it's not longer ok:

class Peel {

    private int peelCount;   
    public Peel(int peelCount) {
        this.peelCount = peelCount;
    }    
    public int getPeelCount() {    
        return peelCount;
    }
}

Modification of class Fruit results in a compile error code.

class Peel {

    private int peelCount;

    public Peel(int peelCount) {
        this.peelCount = peelCount;
    }

    public int getPeelCount() {

        return peelCount;
    }
}

class Fruit {

// Return a Peel object that
// results from the peeling activity.
    public Peel peel() {

        System.out.println("Peeling is appealing.");
        return new Peel(1);
    }
}

The old implementation is broken. That problem can be solve by composition:

class Peel {

    private int peelCount;

    public Peel(int peelCount) {
        this.peelCount = peelCount;
    }

    public int getPeelCount() {

        return peelCount;
    }
}


class Fruit {

// Return int number of pieces of peel that
// resulted from the peeling activity.
public Peel peel() {

System.out.println("Peeling is appealing.");
        return new Peel(1);
    }
}

// Apple must be changed to accomodate
// the change to Fruit
class Apple {

    private Fruit fruit = new Fruit();

    public int peel() {

        Peel peel = fruit.peel();
        return peel.getPeelCount();
    }
}

// This old implementation of Example2
// still works fine.
class Example1 {

    public static void main(String[] args) {

        Apple apple = new Apple();
        int pieces = apple.peel();
    }
}

With the style of composition, apple is no longer is-a relationship with Fruit. It become a has-a. Methods from Fruit are delegated to Apple as inheritance. Here my questions arise:

Is there something wrong with adding new methods to superclass to adapt instead of changing or replacing the old methods, which will break the program structure? As far as I see, by doing this, I can still achieve the same thing as the composition example, as well as I won't have to make a lot of wrapper methods to delegate methods of superclass for each subclass.

interface Talkative{

 public void talk();

}

Animal class family can implement Talkative interface as well as Person class family. What do you think about my conclusion?

Upvotes: 0

Views: 1229

Answers (1)

Stephen C
Stephen C

Reputation: 718678

Basically, you seem to be trying to avoid changing clients that depend on an old API by creating a wrapper class.

Unfortunately, this doesn't work very well. It results in a proliferation of wrapper classes, and other cruft to create the instances of the wrapper classes. If you do to much of this, your codebase / application gets bloated, performance suffers, and your code gets increasingly hard to understand.

Better approaches are:

  • Try to get the APIs right in the first place. (Duh!)
  • If the API change doesn't add significant value or fix something important, put off making it.
  • When you do need to make an API change, do it in a binary compatible way; e.g. add new methods rather than making binary incompatible changes to existing ones. Mark old methods as deprecated if you plan to get rid of them.
  • When you have to make a binary incompatible API change, change all of the code that uses it at the same time.

The @Deprecated tag allows you to give people your APIs warning that a method should no longer be used, while giving them a window in which to fix their code to use the replacement method / alternative approach.

Upvotes: 3

Related Questions