When to implement an interface and when to extend a superclass?

36,162

Solution 1

Use an interface if you want to define a contract. I.e. X must take Y and return Z. It doesn't care how the code is doing that. A class can implement multiple interfaces.

Use an abstract class if you want to define default behaviour in non-abstract methods so that the endusers can reuse it without rewriting it again and again. A class can extend from only one other class. An abstract class with only abstract methods can be as good definied as an interface. An abstract class without any abstract method is recognizeable as the Template Method pattern (see this answer for some real world examples).

An abstract class in turn can perfectly implement an interface whenever you want to provide the enduser freedom in defining the default behaviour.

Solution 2

You should choose an interface if all you want is to define a contract i.e. method signatures that you want the inheriting classes to implement. An interface can have no implementation at all. The inheriting classes are free to choose their own implementation.

Sometimes you want to define partial implementation in a base type and want to leave the rest to inheriting classes. If that is the case, choose an abstract class. An abstract class can define method implementations and variables while leaving some methods as abstract. Extending classes can choose how to implement the abstract methods while they also have the partial implementation provided by the superclass.

One extreme of abstract classes is a pure abstract class - one that has only abstract methods and nothing else. If it comes to pure abstract class vs. an interface, go with the interface. Java allows only single implementation inheritance whereas it allows multiple interface inheritance meaning that a class can implement multiple interfaces but can extend only one class. So choosing a pure abstract class over the interface will mean that the subclass will not be allowed to extend any other class while implementing the abstract methods.

Solution 3

Use an interface to define behavior. User (abstract) classes (and subclasses) to provide implementation. They are not mutually exclusive; they can all work together.

For example, lets say you are defining a data access object. You want your DAO to be able to load data. So put a load method on the interface. This means that anything that wants to call itself a DAO must implement load. Now lets say you need to load A and B. You can create a generic abstract class that is parameterized (generics) to provide the outline on how the load works. You then subclass that abstract class to provide the concrete implementations for A and B.

Solution 4

The main reason for using abstract classes and interfaces are different.

An abstract class should be used when you have classes that have identical implementations for a bunch of methods, but vary in a few.

This may be a bad example, but the most obvious use of abstract classes in the Java framework is within the java.io classes. OutputStream is just a stream of bytes. Where that stream goes to depends entirely on which subclass of OutputStream you're using... FileOutputStream, PipedOutputStream, the output stream created from a java.net.Socket's getOutputStream method...

Note: java.io also uses the Decorator pattern to wrap streams in other streams/readers/writers.

An interface should be used when you just want to guarantee that a class implements a set of methods, but you don't care how.

The most obvious use of interfaces is within the Collections framework.

I don't care how a List adds/removes elements, so long as I can call add(something) and get(0) to put and get elements. It may use an array (ArrayList, CopyOnWriteArrayList), linked list (LinkedList), etc...

The other advantage in using interfaces is that a class may implement more than one. LinkedList is an implementation of both List and Deque.

Solution 5

No one?

http://mindprod.com/jgloss/interfacevsabstract.html

EDIT: I should supply more than a link

Here's a situation. To build on the car example below, consider this

interface Drivable {
    void drive(float miles);
}

abstract class Car implements Drivable { 
    float gallonsOfGas;
    float odometer;
    final float mpg;
    protected Car(float mpg) { gallonsOfGas = 0; odometer = 0; this.mpg = mpg; }
    public void addGas(float gallons) { gallonsOfGas += gallons; }
    public void drive(float miles) { 
        if(miles/mpg > gallonsOfGas) throw new NotEnoughGasException();
        gallonsOfGas -= miles/mpg;
        odometer += miles;
    }
}

class LeakyCar extends Car { // still implements Drivable because of Car
    public addGas(float gallons) { super.addGas(gallons * .8); } // leaky tank
}

class ElectricCar extends Car {
    float electricMiles;
    public void drive(float miles) { // can we drive the whole way electric?
         if(electricMiles > miles) {
             electricMiles -= miles;
             odometer += miles;
             return;                 // early return here
         }
         if(electricMiles > 0) { // exhaust electric miles first
             if((miles-electricMiles)/mpg > gallonsOfGas) 
                 throw new NotEnoughGasException();
             miles -= electricMiles;
             odometer += electricMiles;
             electricMiles = 0;
         }
         // finish driving
         super.drive(miles);
    }
}
Share:
36,162
Agrajag9
Author by

Agrajag9

Updated on July 23, 2020

Comments

  • Agrajag9
    Agrajag9 almost 4 years

    I've been reading a lot about interfaces and class inheritance in Java, and I know how to do both and I think I have a good feel for both. But it seems that nobody ever really compares the two side by side and explains when and why you would want to use one or the other. I have not found a lot of times when implementing an interface would be a better system than extending a superclass.

    So when do you implement an interface and when do you extend a superclass?

  • Sjoerd
    Sjoerd almost 14 years
    That article seems biased against interfaces. E.g. "An abstract class, in contrast, provides more structure.", "[An interface is] slow, requires extra indirection". Also, it does not really address the real problem with abstract classes (tight coupling and hard to read code).
  • Thunderhashy
    Thunderhashy almost 14 years
    I would argue that Car should be an abstract class and not an interface. Ford, Chevy should extend abstract Car class.
  • corsiKa
    corsiKa almost 14 years
    He was saying you could, not that you should. My rule of thumb is "classes ARE things, interfaces DO things" - so, I would have abstract Car extends Drivable as in my example above
  • Gilbert Le Blanc
    Gilbert Le Blanc almost 14 years
    Sure, you could define Car as an abstract class. An interface is a contract with several possible implementations.
  • JavierIEH
    JavierIEH over 7 years
    Just a minor comment on this, you can provide default behavior by using interfaces, you can use the strategy pattern, and have a default strategy on one constructor of your class (and potentially have another constructor which takes any strategy). I think an abstract class makes more sense when you want to provide a "framework" for other consumers of your class to tap into, usually this involves reflection or having several A B C D E methods to be called in a correct order, while allowing you to override some of those. This is awkward to do with just interfaces
  • j3141592653589793238
    j3141592653589793238 over 3 years
    This is a very helpful, real-world example. Thanks.
  • greg
    greg over 2 years
    love the example, however the electric car's odometer reads high , on the plus side, it never uses gas! :-).
  • greg
    greg over 2 years
    first and last links are broken. The second article is not a good argument against the use of inheritance. Its more a mea culpa for author's past mistakes. IMHO of course...