Interfaces vs. Abstract Classes
Tags: java, programming, learning, beginners
Published: 2024-06-17 19:41:25

A class can implement multiple interfaces, but it can only extend one superclass. An interface can be used more or less the same way as an abstract class, but defining an interface is different from defining an abstract class. Table below summarizes the differences.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dpkjca6zoz6i2fqzzw2c.png)

Java allows only _single inheritance_ for class extension but allows _multiple extensions_ for interfaces. For example,

`public class NewClass extends BaseClass
implements Interface1, ..., InterfaceN {
 ...
}`

An interface can inherit other interfaces using the **extends** keyword. Such an interface is called a _subinterface_. For example, **NewInterface** in the following code is a subinterface of **Interface1**, . . . , and **InterfaceN**.

`public interface NewInterface extends Interface1, ... , InterfaceN {
// constants and abstract methods
}`

A class implementing **NewInterface** must implement the abstract methods defined in **NewInterface**, **Interface1**, . . . , and **InterfaceN**. An interface can extend other interfaces but not classes. A class can extend its superclass and implement multiple interfaces.

All classes share a single root, the **Object** class, but there is no single root for interfaces. Like a class, an interface also defines a type. A variable of an interface type can reference any instance of the class that implements the interface. If a class implements an interface, the interface is like a superclass for the class. You can use an interface as a data type and cast a variable of an interface type to its subclass, and vice versa. For example, suppose that c is an instance of **Class2** in Figure below. **c** is also an instance of **Object**, **Class1**, **Interface1**, **Interface1_1**, **Interface1_2**, **Interface2_1**, and **Interface2_2**.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uq4o9l9s7czxfmau4n14.png)

Class names are nouns. Interface names may be adjectives or nouns. Abstract classes and interfaces can both be used to specify common behavior of objects. How do you decide whether to use an interface or a class? In general, a _strong is-a relationship_ that clearly describes a parent-child relationship should be modeled using classes. For example, Gregorian calendar is a calendar, so the relationship between the class **java.util.GregorianCalendar** and **java.util.Calendar** is modeled using class inheritance. A _weak is-a relationship_, also known as an is-kind-of relationship, indicates that an object possesses a certain property. A weak is-a relationship can be modeled using interfaces. For example, all strings are comparable, so the **String** class implements the **Comparable** interface.

In general, interfaces are preferred over abstract classes because an interface can define a common supertype for unrelated classes. Interfaces are more flexible than classes. Consider the **Animal** class. Suppose the **howToEat** method is defined in the **Animal** class, as follows:

`abstract class Animal {
public abstract String howToEat();
}`

Two subclasses of **Animal** are defined as follows:

`class Chicken extends Animal {
 @Override
public String howToEat() {
return "Fry it";
 }
}`

`class Duck extends Animal {
 @Override
public String howToEat() {
return "Roast it";
 }
}`

Given this inheritance hierarchy, polymorphism enables you to hold a reference to a **Chicken** object or a **Duck** object in a variable of type **Animal**, as in the following code:

`public static void main(String[] args) {
Animal animal = new Chicken();
 eat(animal);
animal = new Duck();
 eat(animal);
}`

`public static void eat(Animal animal) {
animal.howToEat();
}`

The JVM dynamically decides which **howToEat** method to invoke based on the actual object that invokes the method.

You can define a subclass of **Animal**. However, there is a restriction: The subclass must be for another animal (e.g., **Turkey**).

Interfaces don’t have this restriction. Interfaces give you more flexibility than classes, because you don’t have to make everything fit into one type of class. You may define the **howToEat()** method in an interface and let it serve as a common supertype for other classes.

For example,

`public static void main(String[] args) {
Edible stuff = new Chicken();
 eat(stuff);
stuff = new Duck();
 eat(stuff);
stuff = new Broccoli();
 eat(stuff);
}`

`public static void eat(Edible stuff) {
stuff.howToEat();
}`

`interface Edible {
public String howToEat();
}`

`class Chicken implements Edible {
 @Override
public String howToEat() {
return "Fry it";
 }
}`

`class Duck implements Edible {
 @Override
public String howToEat() {
return "Roast it";
 }
}`

`class Broccoli implements Edible {
 @Override
public String howToEat() {
return "Stir-fry it";
 }
}`

To define a class that represents edible objects, simply let the class implement the **Edible** interface. The class is now a subtype of the **Edible** type, and any **Edible** object can be passed to invoke the **howToEat** method.