• Post Reply Bookmark Topic Watch Topic
  • New Topic

When should i go for an interface and when for an abstract class  RSS feed

 
Greenhorn
Posts: 9
Eclipse IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
When should i go for an interface and when for an abstract class, other than one reason that interface is flexible as we can implement multiple interface?
 
Rancher
Posts: 779
19
C++ Java MySQL Database Netbeans IDE Oracle Tomcat Server
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I go by this general rule of thumb:

--interfaces are building block that can be added together, as you have already stated, so I can build a "tool box" of sorts using interfaces so there will be known ways of accessing things, yet leaving the implementation up to the individual.

--abstract classes are here is what I think, and there you go--deal with it.

Yes, there are similarities in each approach, but the abstract class is more rigid, in that, you cannot add multiple abstract classes together.
 
himashree rawat
Greenhorn
Posts: 9
Eclipse IDE Java Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Les Morgan wrote:I go by this general rule of thumb:

--interfaces are building block that can be added together, as you have already stated, so I can build a "tool box" of sorts using interfaces so there will be known ways of accessing things, yet leaving the implementation up to the individual.

--abstract classes are here is what I think, and there you go--deal with it.

Yes, there are similarities in each approach, but the abstract class is more rigid, in that, you cannot add multiple abstract classes together.







correct me if I am wrong but as far as interface goes if i have an interface and i want one more method declaration to be added to it than i will have to add that method to every class that is implementing that particular interface, isn't that rigidness too? what can be the solution for the same?
 
Ranch Foreman
Posts: 3072
37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If the interface needs another method to be correct then anything implementing that interface should need that method.

Of course with Java 8 you can provide a default implementation now.
 
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Since Java 8, there's only one reason to use an abstract class: If you want to provide a default implementation that depends on private data. Even in this case, it's almost always best to define an interface anyway, and have the abstract class (partially) implement it.

Let's take a silly example of a restaurant with a manager, only one waiter, and a shy cook who doesn't want to be exposed to the outside world:



In this example, we use an interface for Restaurant, and we can give a default implementation for getDinner() because it only depends on publicly accessible data, namely getWaiter(). Let's say we want to make it easier to implement a Restaurant, by providing an abstract class that implements getWaiter(). This waiter just forwards the order to the cook. We have to do this with an abstract class, because we don't want to expose the cook using a publicly accessible method getCook().

A concrete implementation of Restaurant then only has to extend AbstractRestaurant and define getManager().
 
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is why interfaces must be carefully designed and tested before you publish them for general use. Once they are released for public consumption, it's difficult to change them. Java 8 default interface methods help but you never know how your interface will be used so due diligence requires that all implementations should at least be retested if an interface is modified.

However, if an interface has limited use, like say within only one application, then it's not really too difficult to make the necessary changes with the help of most modern IDEs.

One design principle you should keep in mind when designing interfaces is the Interface Segregation Principle. Basically, keep your interfaces small and focused on representing a cohesive set of capabilities/behaviors. See also the Single Responsibility Principle
 
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
himashree rawat wrote:When should i go for an interface and when for an abstract class, other than one reason that interface is flexible as we can implement multiple interface?

My advice:
Favour interfaces. And not just because they are more "flexible", but because they assume less. And, as Stephan says, you can always provide a partial implementation with an abstract class as well if you want to.

On the flip side, and specifically regarding version 8, I would use default methods sparingly; otherwise you risk your interfaces becoming de facto "implementations", and that is NOT what they were intended for.
What you will generally find is that one (maybe two) methods scream out to be "defaulted", because it's what 98% of designers are likely to want; but as soon as you get to a third, ask yourself if you might not be better off adding an abstract class that actually describes your "default" implementation.

HIH

Winston
 
Ranch Hand
Posts: 83
10
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Which one you should choose depends on the purpose of the code you're writing. The guideline is that interfaces represent a behavior of an object (not a noun, usually ends in -able), while an abstract class represents a type (a noun)

Consider the Comparable interface. This tells anything that implements it that it must have a way to compare two itself to something else, which is a specific behavior. There would be no reason to extend a Comparable, even if you could - it doesn't make any since, since Comparable does not tell you anything about the class that implements it except the one specific thing it was implemented to accomplish.

On the other hand, an abstract class is just like a class, but needs more details before it's ready to be instantiated. Consider an abstract class Person. You might write some methods for it that the user has to create, similarly to an interface, but Person is not a behavior: it is a thing. We want to be able to extend it and create, for example, a Staff class or a Student class, that would inherit from Person. So we can see that this should be an abstract class.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch, Zachary Griggs!

Excellent first post, BTW
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Zachary Griggs wrote:Which one you should choose depends on the purpose of the code you're writing. The guideline is that interfaces represent a behavior of an object (not a noun, usually ends in -able), while an abstract class represents a type (a noun)

Although not all interfaces are named as adjectives (when they end in -able). The Collections API has a number of interfaces that are named as nouns: Collection, List, Set, Map. The point about interfaces representing behavior is spot on though. When behavior has a more important focus rather than type hierarchy, go with an interface. This determination requires careful thought and consideration. Testing (unit + alpha + beta) in typical and atypical usage scenarios, reading, and re-reading code that uses the interface or abstract class goes a long way in determining whether or not you're on the right track with the name itself and/or the choice between interface and abstract class.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Zachary Griggs wrote:Which one you should choose depends on the purpose of the code you're writing.

Totally agree. My suggestion should probably have been prefaced with "all other things being equal".

There would be no reason to extend a Comparable, even if you could - it doesn't make any since, since Comparable does not tell you anything about the class that implements it except the one specific thing it was implemented to accomplish.

Have to disagree here. Not only can you extend interfaces, you should; and for precisely the same reasons you would extend a class - re-use.
Just because "behaviour" doesn't implement anything doesn't mean that you can't build on it.
Comparable is also a bit of an oddball, since its "behaviour" is tied directly to an object. It's "static" counterpart, Comparator, on the other hand, is not; and I have created three extensions to it myself (all for reasons now corrected in version 8).

On the other hand, an abstract class is just like a class, but needs more details before it's ready to be instantiated. Consider an abstract class Person...

Again, I agree with most of what you say, but why shouldn't you just be able to create a Person? Making it abstract assumes that there is something "missing" from the definition, which may or may not be true.
On the other hand, an AbstractList (a "skeleton" implementation) absolutely requires further definition by a designer, so it makes complete sense to make it an abstract class.

My 2 ¢.

Winston
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I guess for me, seeing abstract tells me that I should also carefully consider inheritance relationships whereas with interface it's not so much of a concern. That's what I would intend to communicate to others as well when I use them in my designs.

The conventions used for naming abstract classes and their subclasses can get pretty confusing and there are many opinions about them. You'll commonly see AbstractWhatever, a BaseWhatever, and even an AbstractBaseWhatever. Sorting all these out can leave you pretty I'll typical refer to well-known hierarchies and model my designs after those.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:On the flip side, and specifically regarding version 8, I would use default methods sparingly; otherwise you risk your interfaces becoming de facto "implementations", and that is NOT what they were intended for.

What's wrong with de facto implementations? Can you point out downsides?

Will you please offer your thoughts on the use of default methods here: http://www.coderanch.com/t/665091/java/java/Java-support-multiple-inheritance#3097782
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:What's wrong with de facto implementations? Can you point out downsides?

Sure: Documentation.

A skeleton implementation (ie, an abstract class) will have been set up specifically to provide one and so, one assumes, will be documented with that in mind. Indeed, in the case of something like AbstractList, it has been created to implement a List in a specific way.

An interface, OTOH, isn't supposed to have an implementation, so if you start bashing out a whole raft of default methods for it, you not only have to document its behaviour, but its implementation as well.

Don't get me wrong, I like default methods and think they're long overdue; but I don't think of them as an alternative to an implementation. In fact I can't think of an interface I've ever written where I would want to default more than 2 of its methods (and generally only one).
My worry is though that we will start to see large interfaces written basically as implementations simply because someone wants to use it as a "function"; and that bothers me.

If Java really does want to turn interfaces into de facto implementations, then it should allow the construct 'default final'; and if it does, then I take everything back, even though I hate it because it's mixing apples and oranges. But I'll take it back.

Winston
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:What's wrong with de facto implementations? Can you point out downsides?

Another couple of points occurred to me while I was writing the previous post.

1. Interface methods are, by definition public, and by allowing people to default them, we may be encouraging bad practise - for example, providing a public implementation for a method that in an abstract class we might have made protected, or even package private; or defining constants in an interface so that a default method can use them.

2. Interfaces will start to be written as "skeleton implementations" to take advantage (?) of multiple inheritance.

Simply put: A default method in an interface behaves like a non-final public method in a class, but you don't write it for the same reasons. My worry is that people will start to.

Winston
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:A skeleton implementation (ie, an abstract class) will have been set up specifically to provide one and so, one assumes, will be documented with that in mind.

You and Junilu both have made a fair point here. I will concede that an API client may be less aware of implementation details because they will be less likely to look for them in an interface description.

An interface, OTOH, isn't supposed to have an implementation, so if you start bashing out a whole raft of default methods for it, you not only have to document its behaviour, but its implementation as well.

While I agree that this makes an interface less 'pure', I don't mind it as much because I'm used to Sun/Oracle's "This implementation" documentation convention.

Don't get me wrong, I like default methods and think they're long overdue; but I don't think of them as an alternative to a skeleton implementation. In fact I can't think of an interface I've ever written where I would want to default more than 2 of its methods (and generally only one).
My worry is though that we will start to see large interfaces written basically as implementations simply because someone wants to use it as a "function"; and that bothers me.

No, I don't think they should be written as skeletons. When writing an interface, API design comes first. Only afterwards should the designer consider which of these methods can be implemented using only the semantics of the API already exposed. I think if you look at the Tree example I gave in the other thread, you will see that the default implementations I gave there are very close to the more formal definition of those tree properties. I think if your default implementation takes more than two lines, it doesn't have a place in an interface.

I think what it boils down to is Junilu's stance about loaded guns in the other topic. Should we protect API designers against themselves, and withhold a tool that can be abused? That was the reason Java didn't include operator overloading, a feature I've always missed dearly, despite the fact that it's widely abused in other languages.

If Java really does want to turn interfaces into de facto implementations, then it should allow the construct 'default final'; and if it does, then I take everything back.

Agree. Thankfully next version we're getting private default methods, so maybe final default methods won't be far off.
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
All that is why, in general, I'd stay conservative with this and use it only for the same reasons it was intended by the language designers. Until other uses have been shown to be valid and beneficial, I would prefer to stick with older mechanisms if there were any. For things like traits that Stephan mentioned here or in a related thread, I might even consider delegating that to a separate component that was written in a language that had better support for it, like Scala. It's still a JVM language anyway. Regardless, I definitely wouldn't use them just because I can or because they're this "cool new feature", that would just be wrong.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Winston Gutkowski wrote:1. Interface methods are, by definition public, and by allowing people to default them, we may be encouraging bad practise - for example, providing a public implementation for a method that in an abstract class we might have made protected, or even package private; or defining constants in an interface so that a default method can use them.

Yes, like I said earlier, interface design should come first, only then default implementations. Protected and package private members are for abstract classes, although if Java supported full blown traits, I would see no issue with them containing protected or package private members.

Constants I have no problem with. I'm happy that Java allows constants in interfaces, because that's often where they most naturally belong.

2. Interfaces will start to be written as "skeleton implementations" to take advantage (?) of multiple inheritance.

Java doesn't and will never support multiple inheritance. When implementing two interfaces containing identical default method signatures, the class will be forced to reimplement the method. If two methods have conflicting contracts, they can never both be implemented, default methods or not. For instance, it's not possible to design a class that implements both Set and List.

Simply put: A default method in an interface behaves like a non-final public method in a class, but you don't write it for the same reasons. My worry is that people will start to.

This is a fair concern.
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Stephan van Hulst wrote:While I agree that this makes an interface less 'pure', I don't mind it as much because I'm used to Sun/Oracle's "This implementation" documentation convention.

Which is fine for describing the behaviour of one method. The problem comes when you have a raft of them implemented with some "philosophy" in mind.

Question: Can you "override" a default method in a sub-interface? If you can, then you have the basis for "philosophical" implementations ; if not, you'd better be darn careful what you define as a default method.

Winston
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
For those wondering what traits are, let's consider a hierarchy of animals. Some of these lay eggs:

  • Animal
    • Mammal
      • Human
      • Platypus : EggLaying
    • Bird : EggLaying
      • Ostrich
      • Goose
    • Arachnid : EggLaying
      • Spider
      • Scorpion
    • Insect : EggLaying
      • Bee
      • Ant

As you can see, Birds, Arachnids and Insects lay eggs. Not all Mammals lay eggs, but the Platypus does. We can use an interface EggLaying to show which animals can lay eggs. Let's say that the egg laying process is the same for every animal that can lay eggs. We would like to implement layEgg() once, and reuse the code. We can't do this in an abstract class, because all animals already extend the Animal class. Instead, some OO languages solve this problem by using traits.

Traits are much like a Java interfaces, except they don't become part of the type hierarchy. You can think of a trait as if you copied the code inside a trait, and pasted it into the class that has the trait.
 
Stephan van Hulst
Saloon Keeper
Posts: 7993
143
  • Likes 2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
An interesting answer by Brian Goetz himself. Quoted from StackOverflow:

Brian Goetz wrote:The proximate reason for adding default methods to interfaces was to support interface evolution, but we were well aware that we were going beyond that. Whether you consider that to be "interface evolution++" or "traits--" is a matter of personal interpretation. So, to answer your question about safety ... so long as you stick to what the mechanism actually supports, rather than trying to wishfully stretch it to something it does not support, you should be fine.

A key design goal was that, from the perspective of the client of an interface, default methods should be indistinguishable from "regular" interface methods. The default-ness of a method, therefore, is only interesting to the designer and implementor of the interface.

Here are some use cases that are well within the design goals:

  • Interface evolution. Here, we are adding a new method to an existing interface, which has a sensible default implementation in terms of existing methods on that interface. An example would be adding the forEach method to Collection, where the default implementation is written in terms of the iterator() method.
  • "Optional" methods. Here, the designer of an interface is saying "Implementors need not implement this method if they are willing to live with the limitations in functionality that entails". For example, Iterator.remove was given a default which throws UnsupportedOperationException; since the vast majority of implementations of Iterator have this behavior anyway, the default makes this method essentially optional. (If the behavior from AbstractCollection were expressed as defaults on Collection, we might do the same for the mutative methods.)
  • Convenience methods. These are methods that are strictly for convenience, again generally implemented in terms of non-default methods on the class. The logger() method in your first example is a reasonable illustration of this.
  • Combinators. These are compositional methods that instantiate new instances of the interface based on the current instance. For example, the methods Predicate.and() or Comparator.thenComparing() are examples of combinators.

  • If you provide a default implementation, you should also provide some specification for the default (in the JDK, we use the @implSpec javadoc tag for this) to aid implementors in understanding whether they want to override the method or not. Some defaults, like convenience methods and combinators, are almost never overridden; others, like optional methods, are often overridden. You need to provide enough specification (not just documentation) about what the default promises to do, so the implementor can make a sensible decision about whether they need to override it.
     
    Junilu Lacar
    Sheriff
    Posts: 11494
    180
    Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Thanks for looking into this and finding an authoritative citation. I think what Goetz wrote validates what all three of us have said so far, calling for prudence and documentation while still leaving the door open to innovative uses. A cow for your input and effort.

    NOTE: see also this related topic
     
    Winston Gutkowski
    Bartender
    Posts: 10575
    66
    Eclipse IDE Hibernate Ubuntu
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Junilu Lacar wrote:NOTE: see also this related topic

    I've added my reply to that thread, because it seems to me we've kind of "hijacked" this one.

    Winston
     
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!