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?
Difference between Abstact class and interface
Interface Default Methods in Java 8
Java Interface Static Method
Java Functional Interfaces
Abstract classes versus interfaces in Java 8
Conceptual Difference:
Abstract classes are valid for skeletal (i.e. partial) implementations of interfaces but should not exist without a matching interface.
So when abstract classes are effectively reduced to be low-visibility, skeletal implementations of interfaces, can default methods take this away as well? Decidedly: No! Implementing interfaces almost always requires some or all of those class-building tools which default methods lack. And if some interface doesn’t, it is clearly a special case, which should not lead you astray.
Interface Default Methods in Java 8
Java 8 introduces “Default Method” or (Defender methods) new feature, which allows developer to add new methods to the Interfaces without breaking the existing implementation of these Interface. It provides flexibility to allow Interface define implementation which will use as default in the situation where a concrete Class fails to provide an implementation for that method.
Let consider small example to understand how it works:
The following Class will compile successfully in Java JDK 8,
If you create an instance of OldInterfaceImpl:
Default Method:
Default methods can be provided to an Interface without affecting implementing Classes as it includes an implementation. If each added method in an Interface defined with implementation then no implementing Class is affected. An implementing Class can override the default implementation provided by the Interface.
When we extend an interface that contains a default method, we can perform following,
ForEach method compilation error solved using Default Method
For Java 8, the JDK collections have been extended and forEach method is added to the entire collection (which work in conjunction with lambdas). With conventional way, the code looks like below,
Since this result each implementing Class with compile errors therefore, a default method added with a required implementation in order that the existing implementation should not be changed.
The Iterable Interface with the Default method is below,
The same mechanism has been used to add Stream in JDK Interface without breaking the implementing Classes.
Default Method and Multiple Inheritance Ambiguity Problems
Since java Class can implement multiple Interfaces and each Interface can define default method with same method signature, therefore, the inherited methods can conflict with each other.
Consider below example,
The above code will fail to compile with the following error,
In order to fix this class, we need to provide default method implementation:
Further, if we want to invoke default implementation provided by any of super Interface rather than our own implementation, we can do so as follows,
We can choose any default implementation or both as part of our new method.
Important points about java interface default methods:
Resource Link:
Java Interface Static Method
Java Interface Static Method, code example, static method vs default method
Java interface static method is similar to default method except that we can’t override them in the implementation classes. This feature helps us in avoiding undesired results incase of poor implementation in implementation classes. Let’s look into this with a simple example.
Now let’s see an implementation class that is having isNull() method with poor implementation.
Note that isNull(String str) is a simple class method, it’s not overriding the interface method. For example, if we will add @Override annotation to the isNull() method, it will result in compiler error.
Now when we will run the application, we get following output.
If we make the interface method from static to default, we will get following output.
Java interface static method is visible to interface methods only, if we remove the isNull() method from the MyDataImpl class, we won’t be able to use it for the MyDataImpl object. However like other static methods, we can use interface static methods using class name. For example, a valid statement will be:
Important points about java interface static method:
Java Functional Interfaces
Before I conclude the post, I would like to provide a brief introduction to Functional interfaces. An interface with exactly one abstract method is known as Functional Interface.
A new annotation
@FunctionalInterface
has been introduced to mark an interface as Functional Interface.@FunctionalInterface
annotation is a facility to avoid accidental addition of abstract methods in the functional interfaces. It’s optional but good practice to use it.Functional interfaces are long awaited and much sought out feature of Java 8 because it enables us to use lambda expressions to instantiate them. A new package java.util.function with bunch of functional interfaces are added to provide target types for lambda expressions and method references. We will look into functional interfaces and lambda expressions in the future posts.
Resource Location:
Yes, your responses were technically correct but where you went wrong was not showing them you understand the upsides and downsides of choosing one over the other. Additionally, they were probably concerned/freaked out about compatibility of their codebase with upgrades in the future. This type of response may have helped (in addition to what you said):
Good luck on your next interview!
All your statements are valid except your first statement (after the Java 8 release):
From the documentation page:
Default methods:
An interface can have default methods, but are different than abstract methods in abstract classes.
When you extend an interface that contains a default method, you can do the following:
abstract
.Static Methods:
In addition to default methods, you can define static methods in interfaces. (A static method is a method that is associated with the class in which it is defined rather than with any object. Every instance of the class shares its static methods.)
This makes it easier for you to organize helper methods in your libraries;
Example code from documentation page about
interface
havingstatic
anddefault
methods.Use the below guidelines to chose whether to use an interface or abstract class.
Interface:
Abstract class:
Share code among several closely related classes. It establishes is a relation.
Share common state among related classes ( state can be modified in concrete classes)
Related posts:
Interface vs Abstract Class (general OO)
Implements vs extends: When to use? What's the difference?
By going through these examples, you can understand that
Unrelated classes can have capabilities through interface but related classes change the behaviour through extension of base classes.
An interface is a "contract" where the class that implements the contract promises to implement the methods. An example where I had to write an interface instead of a class was when I was upgrading a game from 2D to 3D. I had to create an interface to share classes between the 2D and the 3D version of the game.
Then I can implement the methods based on the environment, while still being able to call those methods from an object that doesn't know which version of the game that is loading.
public class Adventure extends JFrame implements Playable
public class Dungeon3D extends SimpleApplication implements Playable
public class Main extends SimpleApplication implements AnimEventListener, ActionListener, Playable
Typically, in the gameworld, the world can be an abstract class that performs methods on the game:
From what I understand, an Interface, which is comprised of final variables and methods with no implementations, is implemented by a class to obtain a group of methods or methods that are related to each other. On the other hand, an abstract class, which can contain non-final variables and methods with implementations, is usually used as a guide or as a superclass from which all related or similar classes inherits from. In other words, an abstract class contains all the methods/variables that are shared by all its subclasses.
your answer is right but the interviewer needs you to differentiate according to software engineering perspective not according to the details of Java.
Simple words:
An Interface is like the interface of a shop anything that is shown on it should be there in the shop, so any method in the Interface must be there implemented in the concrete class. Now what if some classes share some exact methods and varies in others. Suppose the Interface is about a shop that contains two things and suppose we have two shops both contain sport equipment but one has clothes extra and the other has shoes extra. So what you do is making an abstract class for Sport that implements the Sports method and leave the other method unimplemented. Abstract class here means that this shop doesn't exist itself but it is the base for other classes/shops. This way you are organising the code, avoiding errors of replicating the code, unifying the code, and ensuring re-usability by some other class.