How should I have explained the difference between an Interface and an Abstract class?

In one of my interviews, I have been asked to explain the difference between an Interface and an Abstract class.

Here's my response:

Methods of a Java interface are implicitly abstract and cannot have implementations. A Java abstract class can have instance methods that implements a default behaviour.

Variables declared in a Java interface are by default final. An abstract class may contain non-final variables.

Members of a Java interface are public by default. A Java abstract class can have the usual flavours of class members like private, protected, etc.

A Java interface should be implemented using keyword “implements”; A Java abstract class should be extended using keyword “extends”.

An interface can extend another Java interface only, an abstract class can extend another Java class and implement multiple Java interfaces.

A Java class can implement multiple interfaces but it can extend only one abstract class.

However, the interviewer was not satisfied, and told me that this description represented "bookish knowledge".

He asked me for a more practical response, explaining when I would choose an abstract class over an interface, using practical examples.

Where did I go wrong?


I will give you an example first:

public interface LoginAuth{
   public String encryptPassword(String pass);
   public void checkDBforUser();
}

Suppose you have 3 databases in your application. Then each and every implementation for that database needs to define the above 2 methods:

public class DBMySQL implements LoginAuth{
          // Needs to implement both methods
}
public class DBOracle implements LoginAuth{
          // Needs to implement both methods
}
public class DBAbc implements LoginAuth{
          // Needs to implement both methods
}

But what if encryptPassword() is not database dependent, and it's the same for each class? Then the above would not be a good approach.

Instead, consider this approach:

public abstract class LoginAuth{
   public String encryptPassword(String pass){
            // Implement the same default behavior here 
            // that is shared by all subclasses.
   }

   // Each subclass needs to provide their own implementation of this only:
   public abstract void checkDBforUser();
}

Now in each child class, we only need to implement one method - the method that is database dependent.


Nothing is perfect in this world. They may have been expecting more of a practical approach.

But after your explanation you could add these lines with a slightly different approach.

  1. Interfaces are rules (rules because you must give an implementation to them that you can't ignore or avoid, so that they are imposed like rules) which works as a common understanding document among various teams in software development.

  2. Interfaces give the idea what is to be done but not how it will be done. So implementation completely depends on developer by following the given rules (means given signature of methods).

  3. Abstract classes may contain abstract declarations, concrete implementations, or both.

  4. Abstract declarations are like rules to be followed and concrete implementations are like guidelines (you can use it as it is or you can ignore it by overriding and giving your own implementation to it).

  5. Moreover which methods with same signature may change the behaviour in different context are provided as interface declarations as rules to implement accordingly in different contexts.

Edit: Java 8 facilitates to define default and static methods in interface.

public interface SomeInterfaceOne {

    void usualAbstractMethod(String inputString);

    default void defaultMethod(String inputString){
        System.out.println("Inside SomeInterfaceOne defaultMethod::"+inputString);
    }
}

Now when a class will implement SomeInterface, it is not mandatory to provide implementation for default methods of interface.

If we have another interface with following methods:

public interface SomeInterfaceTwo {

    void usualAbstractMethod(String inputString);

    default void defaultMethod(String inputString){
        System.out.println("Inside SomeInterfaceTwo defaultMethod::"+inputString);
    }

}

Java doesn’t allow extending multiple classes because it results in the “Diamond Problem” where compiler is not able to decide which superclass method to use. With the default methods, the diamond problem will arise for interfaces too. Because if a class is implementing both

SomeInterfaceOne and SomeInterfaceTwo

and doesn’t implement the common default method, compiler can’t decide which one to chose. To avoid this problem, in java 8 it is mandatory to implement common default methods of different interfaces. If any class is implementing both the above interfaces, it has to provide implementation for defaultMethod() method otherwise compiler will throw compile time error.