DEV Community

Cover image for Do you really understand interfaces?

Posted on • Updated on

Do you really understand interfaces?

Table of Contents:

The lead-up

When I was learning Java in college, I did not understand the use for interfaces.
You can't define functions inside an interface. You can only declare them. You have to have a class implement the interface to define it's functions and then use them.
That's crazy! Pretty worthless piece of crap I would think. I can just write my classes and their functions normally. Why would I declare them in one place and define in another.
I don't even need to declare them. Just write my functions normally in a class. It's totally redundant.

Confused and curious, I asked my teacher why I would ever require to implement an interface.
Almost immediately, she said that interfaces let you achieve multiple inheritance, while normal classes don't - the textbook answer on the difference between classes and interfaces.
And I was like, so? Even if my class can implement multiple interfaces at once, none of them would contain function definitions.
They would all be pretty useless. I can just drop them all and write my class without implementing them. Be it single or multiple, what advantage do I get by using interfaces?
My teacher did not have an answer to that.

With the lack of a proper answer, me and most (if not all) of my friends resigned ourselves to accept that interfaces are some kind of mysterious artifacts. That, given the right incantation, would help us manipulate the space-time continuum, rip through the fabric of Java ecosystem and use multiple inheritance - the fruit that is wrongly forbidden from us.

Meanwhile, we gave the same answer during our engineering vivas that my teacher gave me. And wrote the same in our written exams.
Something felt off though. And I could never digest this.
It wasn't until later, when I dabbled with Android that I really learnt the purpose of interfaces - as a contract which lets you to enforce that, the classes you work with, exhibit certain behavior.

I still come across people whose primary understanding of interfaces is something that allows multiple inheritance in Java.
And that is so ridiculous - saying that interfaces support multiple inheritance while classes don't, when I ask you what's the difference between the two.
It's like saying that the difference between a dog and a horse is that a dog barks while a horse neighs.
While that is indeed true, you must understand that dogs and horses are fundamentally different animals!
If your understanding of a horse is that of a dog that neighs. Then boy! You're going to have a wild time in a farm!

Deadly Diamond of Death

First off, lets understand why multiple inheritance is not allowed in Java.

Consider there's a class 'Animals'. All animals makeNoise().
We derive two child classes from this class - 'Horses' and 'Dogs'. Both of them override the makeNoise() behavior.
Horses makeNoise() by neighing. Dogs makeNoise() by barking.
Now suppose, for whatever godforsaken reason, a mad scientist decides to mix up the genes of Horses and Dogs together, and make a new species of Animals - Horgs.
When the Horgs makeNoise(), will they bark? Or will they neigh?
This is the infamous diamond problem (aka Deadly Diamond of Death) in object-oriented programming.

Graphical representation of the given Animal problem

Java doesn't support multiple inheritance with classes simply because inheriting multiple classes together is problematic.
If a class inherits multiple other classes, and these classes contain functions with the same signature, there arises an ambiguity - when I call the said function with an instance of the inheriting (derived) class, how should it behave?
Out of the many function definitions coming from multiple inherited classes, which should be considered?
And how do I control which definition is used when?

C++ tries to handle the Diamond problem using virtual inheritance and scope resolution.
I'm not really a C++ person. And I don't understand how virtual inheritance works.
But, from what I understand, it requires prior knowledge that a certain function may get involved in multiple inheritance. And it requires to be specially handled.
Now that feels weird to me. I did not find many articles on the topic. So, maybe not many people use it. But, please do recommend me any good material on the topic if you have any.

How interfaces solve the diamond problem?

They don't.
Like I said, they're not a mechanism to allow multiple inheritance. It's just that since interfaces don't have method definitions, they don't have the diamond problem.
That is why you're allowed to implement multiple interfaces. That's all.
But the notion that, the use of interfaces is to enable multiple inheritance, is wrong and far from the truth.

The idea behind interfaces

Consider you're a king. You have a beautiful daughter who has reached the age for marriage.
A lot of princes' from the neighboring nations are eager to marry your daughter. But, you have some basic criteria in mind that they should fulfill before they could be considered to marry your daughter.

  1. The Prince should be able to fight. 'cause that's a necessary skill to have for a prince
  2. The Prince should like reading books. 'cause books contain knowledge. And you'd want your son-in-law to be well-educated and wise.
  3. The Prince should be able to speak Klingon. 'cause that's the sign of a superior man.

You write these requirements down on a big banner and place it above the castle gate.
If a Prince comes and satisfies all these conditions, the gatekeeper awards him a 'Badass Prince' badge and sends him in.
If, however, the prince doesn't meet these requirements, the gatekeeper of the castle won't even allow him inside.

Now, this is exactly the idea behind interfaces.
The banner with the requirements on it is an interface for a 'Badass Prince'. And by enforcing those requirements on the prospective Prince, you're essentially requiring them to implement the 'Badass Prince' interface.
Thus stating, that if a Prince is not a 'Badass Prince' (as defined by your interface), they're not eligible to marry your daughter.

The practical use of interfaces while writing software

If you know a class implements an interface, then you know that class contains concrete implementations of the methods declared in that interface, and you are guaranteed to be able to invoke these methods safely.
β€” StackOverflow answer

Often, different teams work together to develop a product. They may work on different features or segments that are integrated together to form the final product.
In such a case, it is obvious that there will be certain inter-dependencies within the teams.

Say for example, we're building an e-commerce website. One team is developing the 'Add-to-cart' feature (the process before checkout). And another team is working on the online-payment system (the process after checkout).
We definitely can't make the online-payments-team wait and idle till the cart-team has finished and tested their feature.

But then, if both the teams start working on their features in parallel, how do we ensure that we'll be able to integrate the online-payments with the cart? In the end, both the features should come together to form the final product, right?
For example, the online-payments team needs the cart to be cleared on successful payment. But, since the cart is not ready yet, how would the payments-team do that? What function should they call? What parameters should they pass to it? What if the cart team doesn't implement such a function at all? And instead, you have to write logic to remove every product from the cart individually?

To mitigate such problems, both the teams must brainstorm about the technical requirements of their own features and realize the inter-dependencies. Once that is done, both the teams can design appropriate interfaces.
For example, the teams decide that on checkout, the cart-system will provide a MyCart object to the payments-system. This MyCart class must implement the Cart interface that has the following methods:

1. void addProduct(Product product)
2. Product removeProduct(integer productId)
3. List<Product> getProductsFromCart()
4. boolean emptyCart()
Enter fullscreen mode Exit fullscreen mode

If object provided by the cart-system does not come from a class that has implemented the Cart interface, then the payments-system will throw an Exception.

if(!(myCart instanceof Cart)){
    throw new Exception("Expected an instance of Cart");
Enter fullscreen mode Exit fullscreen mode

Due to the principle of abstraction in object oriented programming, the payments-team does not need to know how the emptyCart method works. They just need to know:

  1. that it exists
  2. that it is intended to do what they want (clear all products in the cart)
  3. how to call it (what parameters to pass and what to expect in return).

Out of these, interfaces take care of points 1 and 3. Point 2 is left to the human intellect.

Basically, by asking the cart-team to implement the Cart interface, the payments-team says,

"Hey cart-team,
We are not concerned about the logic and implementation on your side.
But, we require certain functionality to be present in the object that you pass to us. And we require it in a very specific manner (with so and so name, so and so parameters, so and so value returned).
Please implement these exactly as specified so that we can just plug your cart-system into our payment-system. And we can have a seamless integration."

This was just a simple example of when an interface is used. There might be more. But, I hope it helps you to understand what an important role the interfaces play in software development.
If you can think of more examples, please let me know in the comments.

In computing, an interface is a shared boundary across which two or more separate components of a computer system exchange information.
An interface is thus a type definition; anywhere an object can be exchanged (for example, in a function or method call) the type of the object to be exchanged can be defined in terms of one of its implemented interfaces or base-classes rather than specifying the specific class.
β€” Wikipedia

Also, a lot of people relate interfaces with legal contracts. This is because interfaces are based on mutual agreement between two parties; on how one party could use the services of another.
You meet the requirements in the contract. And you shall enjoy our uninterrupted services.
You fall short on the terms of the contract, we shall no longer serve you.

A contract is like a promise between people. It is an understanding, a deal between two or more people or organizations to do certain things.
β€” Arts + Law article

To conclude..

  1. Multiple inheritance is problematic.
  2. Java novices often wrongly associate interfaces with multiple inheritance. That's not what they are for.
  3. An interface is actually a pretty powerful construct that lets you define the requirements of your software component. It also lets you enforce that other software components, that interact with yours, meet those requirements.

Official Oracle documentation

Oracle has provided some really awesome documentation on interfaces. So, please check out the following links and look around.

Top comments (17)

askeridos profile image

Without really reading the article, for me an abstract class is used to group members common to daughter classes; you cannot instantiate it.
An interface cannot also be instantiated, but implements a specific behavior, a kind of contract to a class.

By analogy, let's say you have three classes (Car, Motorcycle and Airplane). One of these three vehicles can take off and land. We could implement to the Avion class an IFlyable interface ('I' for Interface, '-able' for 'able to ... fly', by naming convention) with two methods (takeOff() and land()). Since an interface is a kind of contract, even if there are methods you don't use, you still have to implement them in the class.

In Java, for example:

  • a method coming from an interface is annotated with '@Override'
  • if a method is missing, the program does not work!
gaurang847 profile image

You're right. Your explanation on interfaces and abstract classes both seem to be on point.
However, I would encourage you to share an example where you would personally use an abstract class.

Examples with sample classes help one understand how a thing works. But they may not give enough idea about why or when you should use the thing.
Like, suppose you're working on a small project, maybe building a game.
Under what conditions would you consider creating an abstract class? And why?
Same with interface.

I'll even tell you, write an article on it. It'll be helpful to everyone πŸ˜‰

Btw, Oracle has some awesome documentation on abstract classes too πŸ‘€

askeridos profile image
Adam AUTUORI • Edited


Ok. To illustrate the use of an abstract class, we will start from an Animal class ( abstract-classes-and-interfaces-# / id / r-2181451).

An abstract class designates a concept in its simplest form. So an Animal has a weight and a color of fur. Generally, an Animal Eats, Cries, Drinks and Moves. Each of these methods has no body because the abstract class is used to define the actions that these Animals have IN COMMON.

What is the dog's cry? He barks.
Cat ? He meows.
Lion ? He roars.

askeridos profile image
Adam AUTUORI • Edited


So, each class (Lion, Cat, ...) will be redefined the methods of the abstract class. This highlights the notion of polymorphism: the overload of method applied to inheritance.
All these animals have their own cry, eat their own food, ...

Pay attention to the syntax: if you want to create a Lion, it's an Animal:
Animal jungleKing = new Lion ("Simba");

The abstract class therefore makes it possible to implement members common to more specialized classes (going down in the hierarchy of the classes) and to define all or part of the methods.
You can create a consistent hierarchy even if you only know part of the system.

I hope I have explained well. You can translate the link from OpenClassrooms and read the full course.

Thread Thread
gaurang847 profile image

I read the full course using Google Translate. The translation wasn't perfect. But it worked I guess.
I found it to be a great read.
You explained well. But, I feel you missed the most important point of abstract classes.

We can see that our class Animalis declared abstract and that our daughter classes inherit from it. In addition, our daughter classes only redefine two methods out of four, so we conclude that these two methods must be abstract.

This line is important.
If all the methods in the abstract class are abstract, I see no point in such an abstract class. Since, it is essentially an interface then.

When you write a class that extends another normal class, you can either override the methods from the base class. Or you can leave them untouched.
You'd want to create an abstract class when you know that,

  • there are some methods in the base class that will definitely be overridden in the derived classes.

    eg. cry() - Dog, Cat and Lion each have a different cry

  • there will be some methods that won't be overridden in any of the derived classes.

    eg. walk() - Dog, Cat and Lion each walk the same way.

Whether the walk method is actually overridden in the derived class or not, doesn't matter.
But, an abstract class lets me provide the definition of walk method that I believe will be common in all the derived classes. Basically, it lets me provide a default for the walk method.
And, at the same time, it lets me enforce that the derived classes implement the cry method.

If you already understand this, then great!
But if you didn't, I hope I was clear enough.
Again, I'm more interested in a practical example where you've actually created an abstract class while writing software. So, whenever you do that, I'd be happy to hear about it :)

Thread Thread
askeridos profile image

Yeah, i forgot the principle to define default methods with abstract keyword. Your explanation seems better than mine. Thanks !

askeridos profile image

Yeah, JavaDoc explains better than me abstract classes

rossdrew profile image
Ross • Edited

Your teacher was bad. That's the problem here. An interface is a contract, that is all. This multiple inheritance answer is the type of thing a bedded in C++ dev would answer to why Java has interfaces.

Interfaces are a contract that I will adhere to so that:

a. I can substitute the implementation for another without changing the class which uses it. Therefore we can wire programs together with -for example- DI or Tests.

b. Third parties know the contract and can write functionality for it

gaurang847 profile image

Omg. That is so to-the-point. I love it!
I hope though that if my teacher is reading this, she doesn't realise she's being called out on. Might hurt her πŸ™Š

vexonius profile image

Really enjoyed reading this! Nice job describing the problem. I was also one of those "why would I ever need an interface when I have a class" untill I started working and realizing the conveniences of interfaces. Now I wanna check your other articles :D

gaurang847 profile image

Thanks man! :)
Sadly though, I don't write that often. So, you won't find much :(
But, I intend to fix that. Thinking of committing to publishing an article every month. Let's see.

chari16 profile image
Bhavesh Sadanand Chari

It was very helpful and up to the point.!

gaurang847 profile image

Glad to hear that! πŸ™Œ

kellykels21 profile image
Marke'l Spellman • Edited

Really good read. I never really understood the real purpose of interfaces but this cleared it up πŸ˜πŸ‘πŸ½. I like your writing style. Keep it up!

gaurang847 profile image

Hey man thanks! That meant a lot! β™₯️
So glad to know that it was helpful :)

whiplash5057 profile image
Richard Andrews

Great read. Love the analogies. But I'm a javascript developer and there is no support for interfaces in javascript currently. How would I create a contract for other developers to follow?

gaurang847 profile image

That's a nice question!
You're right. JavaScript is not strongly an object-oriented language and it does not have interfaces. And AFAIK, there's no real way of creating a contract like that in JavaScript.

Also, JavaScript is not statically-typed. So, even if you had interfaces, you could only check for the existence of functions. And not for their return-types or their parameters.
You may use TypeScript though. It supports interfaces, type-checking and works with existing JS code.