• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Abstract class vs Interface

 
Ranch Hand
Posts: 180
Hibernate Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi All,

I would like to know what is the difference between the Abstract class and Interface or rather when shall i go for each of them.

I have one reason with me that when i want my implementer to override my all methods i want interface. i.e. totally i have intially framework which i want my implementer to give an implementation.

Abstract class on the other hand i want some of my methods to be mandatorily overriden whereas some methods i may not.

Why it is said to expose the interface i.e. i do not want other person to know what classes are my implementor if i am talking when i am developing an API.

Regards,
Saurav
 
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Disclaimer: Some will disagree with this
The more modern thinking in Java would remove the extends keyword (and everything would simply extend Object by default).

If you wish to extend an implementation (ie: extend an abstract or concrete class) - favor composition.

ie:



This is a way to indirectly "extend" your class, but doesn't expose it's implementation and doesn't make your code less flexible or depend on the superclass implementation. Also, if you refer to your superclass by it's interface - you've really made yourself implementation-agnostic.

Extends is a dangerous keyword - once applications become more complex you will see how dangerous it can become.

This pattern also clearly illustrates how to interact with interfaces rather than implementation types.

Hope this helps!

[ December 12, 2007: Message edited by: Adam Schaible ]
[ December 12, 2007: Message edited by: Adam Schaible ]
 
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Adam Schaible:
Extends is a dangerous keyword - once applications become more complex you will see how dangerous it can become.



As you anticipated, I disagree. "extends" is only "dangerous" when it is misused. When used wisely, it is quite useful. Design Patterns such as Template Method depend on it, and are by far not deprecated in general.
 
Adam Schaible
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Actually, the template method doesn't depend on implementation inheritance.

Anything that can be achieved using implementation inheritance can be achieved with interfaces and composition - and you're left with a MUCH better design.

Your old abstract class is now concrete, and the "unimplemented" methods delegate to an interface that defines the old abstract methods.

So here's a simple example:



Problems with this: You've exposted your internal API - cannot have private and abstract. You really don't want people calling getWord, but you have no choice.

Also, you really can't change the AbstractProcessor much without having to change it's subclasses (or atleast test them).

Consider the following:



WordService is an interface that defines a method getWord();

I could list some other benefits, I just wanted to clarify that implementation inheritance isn't necessary to achieve the same functionality.
 
saurav sarkar
Ranch Hand
Posts: 180
Hibernate Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


public class Processor { private final WordService wordService; public Processor(WordService wordService) { this.wordService = wordService; } public String returnWord() { return wordService.getWord(); }}




Thanks Adam for your inputs.
If i want to summarise your thoughts i would go this way.

I can not look into my objects of my parent hierarchy.
I know the interface of my parent hierarchy.
In my Class i am aggregating the object from the reference of the Interface.
In this i am becoming implementation agnostic i.e. who implements the interface i dont know.
Please correct me if i am wrong.
 
Adam Schaible
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
That's exactly correct.

However, as you have seen in this thread, I am just a man with an opinion - and others may not see as much value in this solution as I do.

I should have made the returnWord() method private - it simply encapsulates the functionality better.
 
saurav sarkar
Ranch Hand
Posts: 180
Hibernate Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Adam and Ilja for your valuable inputs.
But i am still not very much clear when i say expose the interface not the Class.
Adam when you say that by composition are we going towards Dependency Injection?.Because we are constructing the class or rather giving the behaviour to the class by injecting the interface implemented object.
 
Adam Schaible
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You could look at it like dependency injection. We really aren't "injecting" it right now, but sure - we've setup the class to where it could easily be injected.

"Expose the interface not the class" can mean many different things - for example:



In the first example, we are referring to an implementation by it's interface - this would be considered good practice. One way to force the use of an interface is to provide a "factory" method that works like a constructor, but it's return type is the interface.



If someone wanted an instance of InterfaceExample, they have to use the getInstance() method, which returns it's interface.

Does that help?
 
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
We've rather blown the limits of the beginner forum here. To the original question, the Ranch FAQ may help.
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Adam Schaible:
Actually, the template method doesn't depend on implementation inheritance.



Sure it does. It's *defined* that way.


Anything that can be achieved using implementation inheritance can be achieved with interfaces and composition



True.

and you're left with a MUCH better design.



Not always.

It's true that implementation inheritance leads to stronger coupling than using composition. But there are a number of situation where that coupling doesn't hurt at all, and avoiding it leads to a more complex design without any significant benefits. The Abstract Testcase pattern is a good example: http://c2.com/cgi/wiki?AbstractTestCases




Problems with this: You've exposted your internal API - cannot have private and abstract. You really don't want people calling getWord, but you have no choice.



Make getWord() protected. Problem solved.

Also, you really can't change the AbstractProcessor much without having to change it's subclasses (or at least test them).



I don't see how that changes with delegation. Classes that are used by a lot of other classes need to be more stable than classes that are not. Inheritance doesn't change that much, as far as I can tell.

And you should have an extensive, fully automated suite of tests that you can run at the press of a button, anyway.
 
Adam Schaible
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm aware of the abstract test pattern, and have occasionally used it.

As far has having a full suite of unit tests, I 100% agree - but it's not reality for a large portion of my clients. They would all love to have it, but most of the business budget people don't see it has a value-adding effort (no matter how many times they are told otherwise).


Make getWord() protected. Problem solved.



I didn't really explain myself well enough here. I really don't want to expose intermediate calculations here. Lets say I extend your abstract template, put it in my own package - it definately does have access to getWord() (obviously, it has to implement it).

I design API's to be used by all level's of developers - if something CAN be abused, it will be - using extends begs to be abused.

I know, I know - if everyone uses your software how you want it to be used, it's not dangerous at all - but when people begin to depend on parts of your implementation that you have exposed because you extended something, you're now tied to it.

People can override ALL of your template methods - then send it back into your API.
You can't make your abstract class final (obviously, but you may want)

For the test pattern, it is useful - and using extends in this case isn't that dangerous (generally your tests test YOUR software, thus you have complete control over both the tests and the code that's being tested).

If you're simply wiring code together, extends is fine - when others are using your software, it's dangerous -- and you never know when it will switch from the former to the later.
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Adam Schaible:
As far has having a full suite of unit tests, I 100% agree - but it's not reality for a large portion of my clients. They would all love to have it, but most of the business budget people don't see it has a value-adding effort (no matter how many times they are told otherwise).



In my opinion, that's not even a decision to be made by business people. Just as washing his hands is what is part of a doctors professional behavior, writing tests should be part of a programmers professional behavior. It's simply not negotiable. But that's probably something for a different thread...

If you're simply wiring code together, extends is fine - when others are using your software, it's dangerous -- and you never know when it will switch from the former to the later.



Interestingly, our practice is exactly the opposite: we have external companies develop against our APIs, and we encourage them to *not* implement our interfaces, but to extend from abstract classes we provide that implement those interfaces. The reason being that this way we often can add methods to an interface without breaking all client code - most often it's possible to provide a default implementation in the abstract class.

I think this works for us because we are very clear on which parts of the API are supposed to be overridden, which are supposed to be called, and which methods are supposed to be left alone. If someone misuses the code, he has been warned and has to bear the consequences.
 
author
Posts: 9050
21
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
i agree, this is way beyond a beginner's topic, so better late than never...
 
Stan James
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I design API's to be used by all levels of developers - if something CAN be abused, it will be - using extends begs to be abused.

That's probably a big influence on you. There can be a big difference between designs that enable clients and designs that enforce rules. The worst are designs that don't know which they are doing.

Interestingly, our practice is exactly the opposite: we have external companies develop against our APIs, and we encourage them to *not* implement our interfaces, but to extend from abstract classes we provide that implement those interfaces. The reason being that this way we often can add methods to an interface without breaking all client code - most often it's possible to provide a default implementation in the abstract class.

Fascinating. I've wished I had done that after the fact some times.
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Stan James:
Interestingly, our practice is exactly the opposite: we have external companies develop against our APIs, and we encourage them to *not* implement our interfaces, but to extend from abstract classes we provide that implement those interfaces. The reason being that this way we often can add methods to an interface without breaking all client code - most often it's possible to provide a default implementation in the abstract class.

Fascinating. I've wished I had done that after the fact some times.



We actually stole that practice from Eclipse.
 
Stan James
(instanceof Sidekick)
Posts: 8791
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Eclipse is where I first saw adding new methods in new versions of an interface: SomeInterface2 for example. I was surprised because it felt pretty kludgey but the article was by Gamma. I like the approach you described better from the client point of view, even in concert with versioning.
 
Adam Schaible
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
As far as tests are concerned, I can only test my API code - so I do agree with the doctor analogy, but I can't wash your doctors hands for him.

I don't know if you provide source or not, but I would have concerns as a client extending your implementation - less of a problem if I had the source, but still a problem.

The point of an interface is to layout your contract. In my opinion, once an interface is published, it really shouldn't change. Interfaces should be the "foundation" of your structure.

By extending your abstract classes, you're just choosing to make that your way of sharing your code instead of an interface.

The other (large) problem with extending an abstract class, is that it's usually fairly difficult to quickly and easily "parse" the functionality, and integration points between the child and it's parent.

Using an aggregation/composition model, atleast to me, removes the quagmire of ambiguity. In addition, I feel debugging is much more straight-forward.

Just opinions, but that's what a forum is for!
 
Ilja Preuss
author
Posts: 14112
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Adam Schaible:
As far as tests are concerned, I can only test my API code - so I do agree with the doctor analogy, but I can't wash your doctors hands for him.



Yes. If I were someone delivering tools to doctors, I wouldn't take responsibility for those who don't wash their hands, though. I would simply assume that they do. If those who don't get in trouble while using my tools, well, it's really *their* responsibility.

Admittedly, I'm not as extreme with the code I write. Still, I think the fundamental principle holds.

I don't know if you provide source or not, but I would have concerns as a client extending your implementation - less of a problem if I had the source, but still a problem.



We don't. What concerns?

Note that you don't *have* to extend our base classes. It will just be more work for you if you don't.

The point of an interface is to layout your contract.



Yes. And in a system that evolves over a decade and more, contracts need to change.

In my opinion, once an interface is published, it really shouldn't change. Interfaces should be the "foundation" of your structure.



So, what should we do if we find that the most consistent, coherent way of adding a new feature would require us to add an operation to an existing interface? Serious question.

By extending your abstract classes, you're just choosing to make that your way of sharing your code instead of an interface.



But using this pattern, the shared code really is minimal to non-existent. An abstract class for a new interface contains no code at all, and when an operation is added to an interface, the abstract class will just contain the minimal, reasonable code - often enough an empty implementation. I don't see what's the problem with that practice.

The other (large) problem with extending an abstract class, is that it's usually fairly difficult to quickly and easily "parse" the functionality, and integration points between the child and it's parent.



That might be true for complex abstract base classes. That's not what I'm talking about here, which hopefully is more clear now.

Just opinions, but that's what a forum is for!



Sure. Talking to someone who disagrees with me is what I'm here for! How else would I learn something new?
 
Adam Schaible
Ranch Hand
Posts: 101
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

We don't. What concerns?
Note that you don't *have* to extend our base classes. It will just be more work for you if you don't.


My main concern is I like to understand what's happening. I guess it depends on how close this code is to business critical operations, but I'd rather not enter a black-box. I'd just like to be able to debug through everything, and I can't without the source.

Yes. And in a system that evolves over a decade and more, contracts need to change. So, what should we do if we find that the most consistent, coherent way of adding a new feature would require us to add an operation to an existing interface? Serious question.


It sounds like you're using interfaces for your internal contract, and abstract classes for your external contract. That way, if you want to break the internal contract, you can simply modify your base class so your clients code still works.

To answer the question, your clients should be implementing an interface that defines what they program. Your old abstract classes should have an instance of this interface as a private member. Your old abstract class should delegate to this member for all of the custom stuff - this way their code is decoupled from your implementations, and your clients understand their expectations because they are clearly defined in the contract of the interface they implement. Also, you are free to manipulate your implementations because your clients really don't depend on you, you depend on your clients.

Sometime's I'm not the best at explaining on a forum, but this solution really protects your code from being abused, and your clients mis-using your code, and accidentally plugging in to part of your code that wasn't supposed to be public.

You've also said the abstract classes are just there so you can add methods to them and implement them if you choose - not forcing the client code to be modified. Again, read above.

The solution to all "abstract class" problems, in general, is to write an interface that defines the abstract methods and delegate to it's implementation.

It can get tricky with "optional" overrides. One could argue that overriding, in general, is going down the wrong path. If it's an occasional thing, between the two of us we could discover plenty of good solutions fairly quickly - but I do understand overriding is more difficult.

One pattern I've seen is to simply return null if you want the default implementation. While I really hate intentionally returning null and having it mean something, debugging the code is pretty clear.
 
it's a teeny, tiny, wafer thin ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic