views:

273

answers:

5

Can anyone explain disadvantage of inheritance in java

+5  A: 

you probably want to read:

Effective Java™, Second Edition By: Joshua Bloch

Chapter 4. Classes and Interfaces

Item 16: Favor composition over inheritance

Item 17: Design and document for inheritance or else prohibit it

Item 18: Prefer interfaces to abstract classes

Viele
+3  A: 

Take a loot at Allen Holub's article in JavaWorld entitled Why extends is evil. He discusses things like tight-coupling and the fragile base class problem.

akf
The article does not shun inheritance per se, only extending concrete base classes.
Péter Török
A: 

We prefer composition over inheritance because when we add (particularly) or change functionality by subclassing, we couple that new functionality to the class - so anywhere we need the new functionality, we need that class. That extends even to further subclasses - and with Java's single-inheritance model, if we have two new bits of functionality we want in yet another class, there's no (simple) way to bring both bits in, if each is in a separate subclass of the original ancestor.

By comparison, if we extend functionality via composition, any class - in or out of our existing hierarchy - can incorporate it by simply including the tiny class that has the new function. It's simpler, cleaner, more reusable, and easier to read.

Inheritance has its place, but it's not the right tool for many, many jobs.

Carl Manaster
+1  A: 

Unless your class is designed for inheritance, it should be made final. You have to be very careful to make sure you understand how methods which will be overridden in a sub class which was not designed for inheritance function, so as to understand how to modify them.

A specific example:

Consider you have a class that manages a list of names...

public class MyNameManager {
  private List<String> numbers = new LinkedList<String>();

  public void add(String value) {
    numbers.add(value);
  }

  public void addAll(Collection<String> values) {
    for(String value : values) {
      add(value);
    }
  }

  public void remove(String value) { //... }

  //...
}

Now say you want to create a new subclass which also counts the total number of times a name gets added to the list, like so:

public class MyCountingNameManager extends MyNameManager {
  private int count = 0;

  @Override
  protected void addAll(Collection<String> values) {
    count += values.size();
    super.addAll(values);
  }

  @Override
  protected void add(String value) {
    count += 1;
    super.add(value);
  }
}

Seems pretty straightforward, no? But consider the result of the following:

MyCountingNameManager m = new MyCountingNameManager();
m.add("bob");
m.add("Sally");

The count is now 2, and all is well. But if we were to do the following:

List<String> family = new List<String>();
family.add("mom");
family.add("dad");
family.add("brother");

MyCountingNameManager m = new MyCountingNameManager();
m.add(family);

The count is now 6, not the 3 you'd probably expect. This is because the call to addAll adds the size of the Collection of values (which is 3) to the count, and then calls the super.addAll method to do the actual processing. super.addAll iterates the Collection and calls the add method for each value. But since we're working in an MyCountingNameManager and not a MyNameManager, the overridden add method in the sub class is called each time. The MyCountingNameManager.add method which gets executed also increments the count! So the result is each name gets counted twice!

I believe this example comes from Effective Java. You should definitely find a copy and read the items listed in Viele's answer for a deeper understanding of some cases where inheritance is a bad fit.

Tom Tresansky