Domanda

I had an interview where interviewer asked me first what is the difference between abstract class with all the methods abstract and an interface.

I replied that if it is required to inherit something in the future you will not be able to do it if you have already extended a class.

Then, he stated that it was a situation where one would never have to extend any other class and you have to implement a contract. In this circumstance, which would be better, an abstract class or an interface?

I told him you can use either of them but he was not satisfied. I could not understand why - I believe that is a developer/design choice.

È stato utile?

Soluzione

The answer stating that an interface represents a contract is not acceptable. That's the answer we give to Junior since it may be too complex to clearly figure out the difference between the essence of an abstract class and the essence of an interface without much architecture experience and without reading a lot of classic books about. Any abstract class with public methods acts as a contract, as well as an interface.

An abstract class that doesn't provide any implementation is in 99% of cases a representation of an object's Role.
An interface represents a Role.
Each object might have several different roles that shouldn't be tied together but composed by the concerned object.

I'm explaining this with this example:

Your interviewer could say:
I have a Robot that can walk and a Human that can walk too.

So based on this case, he asks you: should I extract the walking feature in an abstract base class or in an interface, knowing that the implementations have nothing in common?

You think..."oh I know so: in this case, having one abstract class with an abstract method walk(), then is clearly the same than declaring an interface with the walk() method."
So your answer would surely be: "it's the choice of the developer !".
And it's really not an always valid answer.

Why? Let's see the next expectation:
A Human can eat, but obviously the Robot cannot and even doesn't need.

What if you implemented the walking feature with an abstract class? You would end up with:

public abstract class Biped {  
  public void abstract walk();
} 

public Robot extends Biped {
   public void walk() {
     //walk at 10km/h speed
   }
}

public Human extends Biped {
   public void walk() {
     //walk at 5km/h speed
   }
}

How could you plug the eating feature? You're stuck because you can't implement it in the Biped base class since it would break Liskov Substitution Principle, since a Robot doesn't eat! And you can't expect Human extending another base class due to the known Java rule.

Of course, you could add a specific Feedable interface only dedicated to Human:

public interface Feedable {
  void eat();
} 

Signature becomes: public Human extends Biped implements Feedable { Clearly, it makes no sense and confusing to have one role implemented through a class and the other through an interface.

That's why starting with interface is really preferred whenever we have the choice.

With an interface, we can model Roles easily by composing.

So the final solution would then be:

public interface Walkable {
   void abstract walk();
} 

public interface Feedable {
   void eat();
} 

public Robot implements Walkable {
   public void walk() {
     //walk at 10km/h speed
   }
}

public Human implements Walkable, Feedable {
   public void walk() {
     //walk at 5km/h speed
   }

   public void eat(){
     //...
   }    
}

Doesn't it remind you the Interface Segregation Principle? ;)

To sum up, if you specify an IS-A relationship, uses an abstract class. If you realize that you are about to model a Role (let's say a IS-CAPABLE-OF relationship), go with interface.

Altri suggerimenti

Here are the differences:

  1. A class can extend exactly abstract class, but can implement any number of interfaces.
  2. An abstract class can have protected, private (does not apply to your question), package, and public methods, but an interface can only have public methods.
  3. An abstract class can have instance variables (often called data members or properties) while an interface can only have static variables.

The answer to the question: "blah never extend blah implement contract blah" is this: "I would use an abstract class if I did needed instance variables and/or non-public methods and otherwise I would use an interface".

Interfaces are the natural way of creating a contract because they force you to implement the methods they define.

Besides that, you can implement as many as you want in the case you want to add new interfaces to your class.

I can't say what your interviewer had in mind, but an interface is more of a "contract" whereas an abstract base class, while it can play that role too, is more geared towards hierarchies or IS-A relationships. E.g. an Apple IS-A Fruit, a Pear IS-A Fruit, etc. But you're right, they could well be used interchangeably for practical purposes in that context, but an OO purist might not want to use an abstract class unless they were expressing IS-A relationship(s).

One thing to keep in mind is be the ability to have diamond inheritance for interfaces.

Consider this interface hierarchy:

interface Base{}

interface Sub1 extends Base{}

interface Sub2 extends Base{}

interface SubSub extends Sub1, Sub2{}

The same wouldn't be possible with abstract classes:

abstract class Base{}

abstract class Sub1 extends Base{}

abstract class Sub2 extends Base{}

// NOT ALLOWED! can only extend one class
// abstract class SubSub extends Sub1, Sub2{}

This is something that would be allowed in C++ (although tricky to get right). I think he might have been fishing for this. In general, this is the ultimate reason why I always try to write interface hierarchies instead of class hierarchies.

For the first situation i'd chose interface over abstract class with all methods abstract as having interface leaves me with option in future for my implementing class to extend some other (abstract) class.

For second scenario, if you really don't want your concrete class to extend any other class and also want to "implement" contract, you can have abstract class with all methods abstract.

I can see such question was already answered. BTW, I would like to share what I consider the best explanation I have read so far.

The bellow text was copied and pasted from Deshmukh, Hanumant. OCP Oracle Certified Professional Java SE 11 Programmer I Exam Fundamentals 1Z0-815: Study guide for passing the OCP Java 11 Developer Certification Part 1 Exam 1Z0-815 (p. 319). Enthuware. Edição do Kindle.

13.2 Distinguish class inheritance from interface inheritance including abstract classes 13.2.1 Difference between Interface and Abstract Class ☝

"What is the difference between an interface and an abstract class" is usually the first question that is asked in a Java "tech-check". While being a simple ice breaker, it also an excellent question to judge a candidate's understanding of OOP. Candidates usually start parroting the technical differences such as an interface cannot have method implementations (which it can, since Java 8), while abstract class can. An interface cannot have static methods (which it can, since Java 8) or instance fields while an abstract class can and so on. All that is correct, but is not really impressive. The fundamental difference between an interface and an abstract class is that an interface defines just the behavior. An interface tells you nothing about the actual object other than how it behaves. An abstract class, on the other hand, defines an object, which in turn, drives the behavior. If you understand this concept everything else about them will fall in place. For example, "movement" is a behavior that is displayed by various kinds of objects such as a Car, a Cat, or a StockPrice. These objects have no commonality except that they move. Saying it the other way round, if you get an object that "moves", you don't get any idea about what kind of an object are you going to deal with. It could be a Car, a Cat, or a StockPrice. If you were to capture this behavior in Java, you would use an interface named Movable with a method named move(). On the other hand, if you talk about Automobile, a picture of an object starts forming in your head immediately. You can sense that an Automobile would be something that would have an engine, would have wheels, and would move. You intuitively know that a StockPrice or a Cat cannot be an Automobile even though they both do move. An abstract class is meant exactly for this purpose, when, once you identify a conceptual object, you do not need to worry about its behavior. The behavior kind of flows automatically. If you create an abstract class named Automobile, you are almost certain that it would have methods such a move, turn, accelerate, or brake. It would have fields for capturing inner details such Engine, Wheels, and Gears. You get all that just by saying the word Automobile. From the above discussion, it should be clear that interfaces and abstract classes are not interchangeable. Even though an abstract class with no non-abstract method looks functionally similar to an interface, both are fundamentally different. If you are capturing a behavior, you must use an interface. If you are capturing a conceptual object, you must use an abstract class.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top