When to Use Abstract Class or Interface

When to use an interface instead of an abstract class and vice versa?

I wrote an article about that:

Abstract classes and interfaces

Summarizing:

When we talk about abstract classes we are defining characteristics of an object type; specifying what an object is.

When we talk about an interface and define capabilities that we promise to provide, we are talking about establishing a contract about what the object can do.

When do I have to use interfaces instead of abstract classes?

From Java How to Program about abstract classes:

Because they’re used only as superclasses in inheritance hierarchies,
we refer to them as abstract superclasses. These classes cannot be
used to instantiate objects, because abstract classes are incomplete.

Subclasses must declare the “missing pieces” to become “concrete” classes,
from which you can instantiate objects. Otherwise, these subclasses, too,
will be abstract.

To answer your question "What is the reason to use interfaces?":

An abstract class’s purpose is to provide an appropriate superclass
from which other classes can inherit and thus share a common design.

As opposed to an interface:

An interface describes a set of methods that can be called on an
object, but does not provide concrete implementations for all the
methods
... Once a class implements an interface, all objects of that class have
an is-a relationship with the interface type, and all objects of the
class are guaranteed to provide the functionality described by the
interface.
This is true of all subclasses of that class as well.

So, to answer your question "I was wondering when I should use interfaces", I think you should use interfaces when you want a full implementation and use abstract classes when you want partial pieces for your design (for reusability)

When to use abstract class or interface?

Interface is used when you only want to declare which methods and members a class MUST have. Anyone implementing the interface will have to declare and implement the methods listed by the interface.

If you also want to have a default implementation, use abstract class. Any class extending the abstract class will have to implement only its abstract methods and members, and will have some default implementation of the other methods of the abstract class, which you may override or not.

--EDIT - forgot to mention, Earwicker reminded me

Finally, you can implement as many interfaces as you want, but only extend one class (being it abstract or not). Keep that in mind before choosing.

When to use interface vs abstract class after Java 8

default methods on interface

Apparently you are referring to the feature of “default methods” implementing behavior in an interface.

You should understand that the feature was added as a way around this dilemma: How to retroactively add features leveraging streams and lambda on existing interfaces without breaking existing classes that implement those interfaces?

Many new methods were added to those interfaces such as in the Java Collections Framework. Adding methods to an existing interface would automatically break all classes implementing the interface that are lacking the newly-required methods. Being able to provide a fallback, to give an implementation where one is now required but not yet existing, would resolve the dilemma. Thus « default methods » were born.

To quote from the Oracle tutorial linked above:

Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces.

To quote this Answer by Brian Goetz, Java Language Architect at Oracle:

The proximate reason for adding default methods to interfaces was to support interface evolution

So this feature of adding default behavior to an interface was not meant to be a new mainstream feature in and of itself. The intent of default was not to replace abstract.

Indeed, some experienced Java experts have recommended against making a habit of writing default methods on an interface. They recommend pretty much ignoring that feature of the Java language. Continue to think of interfaces as simply defining a contract, and abstract classes as providing partial implementations meant to be completed in a subclass.

You are certainly free to write your own default methods on your interfaces. And certainly you should do so if you are in a similar situation of having published an interface that others may have implemented, and now you want to add methods. But unnecessarily adding default methods is likely to confuse other programmers who expect partial implementations on an abstract class rather than an interface.

Four situations calling for default method on an interface

In that same post linked above, Brian Goetz suggests three other cases beyond interface evolution where default methods on an interface may be appropriate. Here is a quick mention; see his post for details.

  • Optional methods - The default method throws an UnsupportedOperationException because we expect implementations of this interface to more often not want to implement this method.
  • Convenience methods
  • Combinators

Start with interface, move to abstract class for shared code

As for choosing between an interface and abstract class:

  • Generally start with an interface. Or several interfaces if you want various implementing classes to mix various contracts (see mixin).
    • Think twice before adding a default method. Consider if your situation meets one of the four cases recommended by Brian Goetz as discussed above.
  • If you come to realize that you have duplicated code across multiple classes, then consider centralizing that shared code to an abstract class to be used across subclasses.
    • Alternatively, use composition rather than inheritance (discussed below).

For example, you might have a class for domestic ShippingLabelUS as well as ShippingLabelCanada and ShippingLabelOverseas. All three need to convert between imperial pounds and metric kilograms. You find yourself copying that code between the classes. At this point you might consider having all three classes extend from abstract class ShippingLabel where a single copy of the weight conversion methods live.

While designing your API keep in mind that Java, like most OOP languages, has single-inheritance. So your subclasses are limited to extending only one class. To be a bit more specific about the single-versus-multiple inheritance, I will quote Brian Goetz from this PDF of a slide deck:

[regarding default methods on an interface]

Wait,is this multiple inheritance in Java?

• Java always had multiple inheritance of types

• This adds multiple inheritance of behavior

• But not of state, where most of the trouble comes from

Composition over inheritance

An alternative to using an abstract class for shared behavior is creating a separate class for specific behavior, then adding an object of that separate class to be kept as a member field on the larger class. Wise programmers often share this pearl of wisdom: Prefer composition over inheritance.

Regarding the shipping label example above, you could create a WeightConverter class, an object of which would be a member of each of the three label classes. In this arrangement, no need for the abstract class.

What happens when an abstract class implements an interface in Java

You can imagine an abstract class as an unfinished class. It's like a template for actual real classes. Interfaces are mainly used to describe properties, like CanWalk, IsCloseable, HasAName and so on.

There is no big difference between both concepts from the language perspective, other than that you can only extend from one class but are allowed to implement multiple interfaces.

In the end of the inheritance chain you will always have non-abstract concrete classes. Which is obvious, you can't use unfinished classes in the end, you need to finish them. That's why

Animal animal = new Animal();

does not work if Animal is abstract. We need to create instances of finished classes, like a Dog who extends from Animal.


And at that point, where you have a finished (non-abstract) class, all abstract methods need to be implemented. It doesn't matter from where those methods come from, abstract classes or interfaces, they need to be implemented.

So if you have an abstract class and implement an interface with it, you have two options for the interface methods. You either

  • implement them in the abstract class or
  • you leave them abstract, but then some of your more concrete children need to implement it.

Example

Let's suppose we have an interface like

public interface CanMakeNoise {
void makeNoise();
}

and the abstract class

public abstract class Animal implements CanMakeNoise {
public abstract void jump();

...
}

together with a concrete extending class

public class Dog extends Animal {
...
}

Since Dog is not abstract, all methods need to be implemented. That is, we need implementations for jump and makeNoise. For the makeNoise method we have two options, either Animal implements it or it leaves it abstract, then Dog needs to implement it:

// Variant 1
public abstract class Animal implements CanMakeNoise {
public abstract void jump();

@Override
public void makeNoise() {
System.out.println("hello, what's up");
}
}

or

// Variant 2
public abstract class Animal implements CanMakeNoise {
public abstract void jump();
}

public class Dog extends Animal {
@Override
public void makeNoise() {
System.out.println("Wuff wuff");
}
}

And of course Dog needs to implement jump:

public class Dog extends Animal {
@Override
public void jump() {
System.out.println("Boing");
}

...
}

In this case it's probably better to leave the implementation of makeNoise up to more concrete classes since Animal has no clue how a specific animal will sound like.

Extending the example, if you have even more concrete classes like a Chihuahua extends Dog, you could implement the makeNoise in Dog since all dogs do "Wuff, wuff".

How do you decide between using an Abstract Class and an Interface?

Use an abstract class if you have some functionality that you want it's subclasses to have. For instance, if you have a set of functions that you want all of the base abstract class's subclasses to have.

Use an interface if you just want a general contract on behavior/functionality. If you have a function or object that you want to take in a set of different objects, use an interface. Then you can change out the object that is passed in, without changing the method or object that is taking it.

Interfaces are typically loose, compared to Abstract classes. You wouldn't want to use interfaces in a situation where you are constantly writing the same code for all of the interface's methods. Use an abstract class and define each method once.

Also, if you are trying to create a specific object inheritance hierarchy, you really wouldn't want to try to do that with just interfaces.

Also, again, in some languages you can only have a single base class, and if an object already has a base class, you are going to have to do some refactoring in order to use an abstract base class. This may or may not mean that you might want to use an inteface instead.

As @tvanfosson notes, it's not a bad idea to use a lot of interfaces, when you really understand abstract classes and interfaces, it's not really an either/or situation. A particular situation could use both abstract classes and interfaces or neither. I like to use interfaces sometimes simply to restrict what a method or object can access on a passed in parameter object.



Related Topics



Leave a reply



Submit