39

I used to create a lot of abstract classes / methods. Then I started using interfaces.

Now I am not sure if interfaces aren't making abstract classes obsolete.

You need a fully abstract class? Create an interface instead. You need an abstract class with some implementation in it? Create an interface, create a class. Inherit the class, implement the interface. An additional benefit is that some classes may not need the parent class, but will just implement the interface.

So, are abstract classes / methods obsolete?

6
  • How about if your programming language of choice does not support interfaces? I seem to recall this is the case for C++.
    – Bernard
    Commented Jul 21, 2011 at 15:48
  • 7
    @Bernard: in C++, an abstract class is an interface in all but name. That they can also do more than 'pure' interfaces is not a disadvantage.
    – gbjbaanb
    Commented Jul 21, 2011 at 15:51
  • @gbjbaanb: I suppose. I don't recall using them as interfaces, but rather to provide default implementations.
    – Bernard
    Commented Jul 21, 2011 at 16:01
  • Interfaces are the "currency" of object references. Generally speaking they are the fundament of polymorphic behavior. Abstract classes serve a different purpose that deadalnix explained perfectly.
    – jiggy
    Commented Jul 21, 2011 at 16:56
  • 4
    Isn't this like saying "are modes of transport obsolete now we have cars?" Yeah, most of the time, you use a car. But whether you ever need anything other than a car or not, it wouldn't really be correct to say "I don't need to use modes of transport". An interface is much the same as an abstract class without any implementation, and with a special name, no?
    – Jack V.
    Commented Jul 22, 2011 at 9:11

11 Answers 11

114

No.

Interfaces cannot provide default implementation, abstract classes and method can. This is especially usefull to avoid code duplication in many cases.

This is also a really nice way to reduce sequential coupling. Without abstract method/classes, you cannot implement template method pattern. I suggest you look at this wikipedia article : http://en.wikipedia.org/wiki/Template_method_pattern

16
  • 3
    @deadalnix Template method pattern can be quite dangerous. You can easily end up with highly coupled code, and start hacking the code to extend the templated abstract class to handle "just one more case".
    – quant_dev
    Commented Jul 21, 2011 at 17:20
  • 13
    This seems more like an anti-pattern. You can get exactly the same thing with composition against an interface. Same thing applies to partial classes with some abstract methods. Rather then forcing client code to subclass and override them, you should have the implementation be injected. See: en.wikipedia.org/wiki/Composition_over_inheritance#Benefits
    – back2dos
    Commented Jul 21, 2011 at 21:17
  • 6
    This doesn't explain AT ALL how to reduce sequential coupling. I do agree that several ways exists to achieve this goal, but please, answer the problem you are talking about instead of blindly invoke some principle. You'll ends up doing cargo cult programming if you can't explain why this is related to the actual problem.
    – deadalnix
    Commented Jul 21, 2011 at 21:27
  • 4
    @deadalnix: Saying that sequential coupling is best reduced with the template pattern is cargo cult programming (using the state/strategy/factory pattern may just work as well), as is the assumption that it must always be reduced. Sequential coupling is often a mere consequence of exposing very fine grained control over something, meaning nothing but a trade-off. That still doesn't mean I can't write a wrapper that does not have sequential coupling using composition. In fact, it makes it a lot easier.
    – back2dos
    Commented Jul 22, 2011 at 7:30
  • 4
    Java now has default implementations for interfaces. Does that change the answer? Commented Oct 20, 2014 at 12:32
15

An abstract method exists so you can call it from within your base class but implement it in a derived class. So your base class knows:

public void DoTask()
{
    doSetup();
    DoWork();
    doCleanup();
}

protected abstract void DoWork();

That's a reasonably nice way to implement a hole in the middle pattern without the derived class knowing about the setup and cleanup activities. Without abstract methods, you'd have to rely on the derived class implementing DoTask and remembering to call base.DoSetup() and base.DoCleanup() all the time.

Edit

Also, thanks to deadalnix for posting a link to the Template Method Pattern, which is what I've described above without actually knowing the name. :)

4
  • 2
    +1, I prefer your answer to deadalnix'. Note that you can implement a template method in a more straight-forward way using delegates (in C#): public void DoTask(Action doWork)
    – Joh
    Commented Jul 25, 2011 at 9:09
  • 2
    @Joh - true, but that's not necessarily as nice, depending on your API. If your base class is Fruit and your derived class is Apple, you want to call myApple.Eat(), not myApple.Eat((a) => howToEatApple(a)). Also, you don't want Apple to have to call base.Eat(() => this.howToEatMe()). I think it's cleaner just to override an abstract method. Commented Jul 25, 2011 at 14:03
  • 1
    @Scott Whitlock: Your example using apples and fruits is a bit too detached from reality to judge whether going for inheritance is preferable to delegates in general. Obviously, the answer is "it depends", so it leaves plenty of room for debates... Anyway, I find that template methods occur a lot during refactoring, e.g. when removing duplicate code. In such cases, I usually don't want to mess with the type hierarchy, and I prefer to stay away from inheritance. This kind of surgery is easier to do with lambdas.
    – Joh
    Commented Jul 27, 2011 at 10:18
  • 1
    This question illustrates more than a simple application of the Template Method pattern - the public/non-public aspect is known in the C++ community as the Non Virtual Interface pattern. By having a public non-virtual function wrap the virtual one - even if initially the former does nothing but call the latter - you leave a point of customisation for setup/cleanup, logging, profiling, security checks etc. that might be needed later.
    – Tony
    Commented May 10, 2014 at 2:27
10

No, They are not obsolete.

In fact, there is an obscure but fundamental difference between Abstract Classes/Methods and Interfaces.

if the set of classes in which one of these has to be used have a common behaviour that they share (related classes, i mean), then go for Abstract classes/methods.

Example: clerk, Officer, Director -all these classes have CalculateSalary() in common, use abstract base classes.CalculateSalary() canbe differently implemented but there are certain other things like GetAttendance() for example which has a common definition in base class.

If your classes have nothing common(Unrelated classes, in the context chosen) in between them but has an action that is greatly different in implementation, then go for Interface.

Example: cow, bench, car, telesope-not related classes but Isortable can be there to sort them in an array.

This difference is usually ignored when approached from a polymorphic perspective. But I personally feel that there are situations where one is an apt than the other for the reason explained above.

7

In addition to the other good answers, there is a fundamental difference between interfaces and abstract classes that no one has mentioned specifically, namely that interfaces are far less reliable and therefore impose a much greater test burden than abstract classes. For example, consider this C# code:

public abstract class Frobber
{
    private Frobber() {}
    public abstract void Frob(Frotz frotz);
    private class GreenFrobber : Frobber
    { ... }
    private class RedFrobber : Frobber
    { ... }
    public static Frobber GetFrobber(bool b) { ... } // return a green or red frobber
}

public sealed class Frotz
{
    public void Frobbit(Frobber frobber)
    {
         ...
         frobber.Frob(this);
         ...
    }
}

I am guaranteed that there are only two code paths I need to test. The author of Frobbit can rely on the fact that the frobber is either red or green.

If instead we say:

public interface IFrobber
{
    void Frob(Frotz frotz);
}
public class GreenFrobber : IFrobber
{ ... }
public class RedFrobber : Frobber
{ ... }

public sealed class Frotz
{
    public void Frobbit(IFrobber frobber)
    {
         ...
         frobber.Frob(this);
         ...
    }
}

I now know absolutely nothing about the effects of that call to Frob there. I need to be sure that all the code in Frobbit is robust against any possible implementation of IFrobber, even implementations by people who are incompetent (bad) or actively hostile to me or my users (far worse).

Abstract classes allow you to avoid all these problems; use them!

13
  • 2
    The problem you speak of should be solved by using algebraic data types, rather than bending classes to a point where they violate the open/closed principle.
    – back2dos
    Commented Jul 21, 2011 at 21:58
  • 2
    Firstly, I never said it is good or moral. You put that in my mouth. Secondly (being my actual point): It's nothing but a poor excuse for a missing language feature. Lastly, there's a solution without abstract classes: pastebin.com/DxEh8Qfz. In contrast to that, your approach uses nested and abstract classes, throwing all but the code requiring the safety together into a big ball of mud. There is no good reason why RedFrobber or GreenFrobber should be tied to the constraints you want to enforce. It increases coupling and locks in many decisions without any benefit.
    – back2dos
    Commented Jul 22, 2011 at 7:17
  • 1
    Saying that abstract methods are obsolete is wrong with no doubt, but claiming on the other hand that they should be preferred over interfaces is misguiding. They are simply a tool for solving different problems than interfaces.
    – vgru
    Commented Jul 22, 2011 at 9:37
  • 1
    A moral principle is "love thy neighbour". All principles are about what qualities something should have. Principles are neither good, nor bad. The qualities they demand are, and the people using them are. Maintainability is a good quality and flexibility is a part of it. I provided a solution that is just as robust but far more modular and flexible. You're only distracting from the fact, that your point is void thus far, because your example doesn't hold.
    – back2dos
    Commented Jul 23, 2011 at 8:13
  • 3
    "there is a fundamental difference [...] interfaces are far less reliable [...] than abstract classes". I disagree, the difference you have illustrated in your code relies on access restrictions, which I don't think have any reason to differ significantly between interfaces and abstract classes. It may be so in C#, but the question is language-agnostic.
    – Joh
    Commented Jul 25, 2011 at 9:15
4

You say it yourself:

You need an abstract class with some implementation in it? Create an interface, create a class. Inherit the class, implement the interface

that sounds a lot of work compared to 'inherit the abstract class'. You can make work for yourself by approaching code from a 'purist' view, but I find I have enough to do already without trying to add to my workload for no practical benefit.

2
  • Not to mention that if the class doesn't inherit the interface (which was not mentioned it should), you have to write forwarding functions in some languages.
    – Sjoerd
    Commented Jul 21, 2011 at 17:25
  • Umm, the additional "Lot of work" you mentioned is that you created an interface and had the classes implement it--does that really seem like a lot of work? On top of that, of course, the interface gives you the ability to implement the interface from a new hierarchy which wouldn't work with an abstract base class.
    – Bill K
    Commented Dec 20, 2011 at 21:11
4

As I commented on @deadnix post: Partial implementations are an anti-pattern, despite the fact that template pattern formalizes them.

A clean solution for this wikipedia example of the template pattern:

interface Game {
    void initialize(int playersCount);
    void makePlay(int player);
    boolean done();
    void finished();
    void printWinner();
}
class GameRunner {
    public void playOneGame(int playersCount, Game game) {
        game.initialize(playersCount);
        int j = 0;
        for (int i = 0; !game.finished(); i++)
             game.makePlay(i % playersCount);
        game.printWinner();
    }
} 
class Monopoly implements Game {
     //... implementation
}

This solution is better, because it uses composition instead of inheritance. The template pattern introduces a dependency between the implementation of the Monopoly rules and the implementation of how games are to be run. However these are two entirely different responsibilities and there is no good reason to couple them.

1
  • +1. As a side-note: "Partial implementations are an anti-pattern, despite the fact that template pattern formalizes them.". The description on wikipedia defines the pattern cleanly, only the code example is "wrong" (in the sense that it uses inheritance when it's not needed and a simpler alternative exists, as illustrated above). In other words, I don't think the pattern itself is to blame, only the way people tend to implement it.
    – Joh
    Commented Jul 25, 2011 at 9:21
2

No. Even your proposed alternative includes the use of abstract classes. In addition, since you didn't specify the language, then I'm going to go right ahead and say that generic code is the better option than brittle inheritance anyway. Abstract classes have significant advantages over interfaces.

1
  • -1. I don't understand what "generic code vs inheritance" has to do with the question. You should illustrate or justify why "abstract classes have significant advantages over interfaces".
    – Joh
    Commented Jul 25, 2011 at 9:25
1

Abstract classes are not interfaces. They're classes that can't be instantiated.

You need a fully abstract class? Create an interface instead. You need an abstract class with some implementation in it? Create an interface, create a class. Inherit the class, implement the interface. An additional benefit is that some classes may not need the parent class, but will just implement the interface.

But then you would have a non-abstract useless class. Abstract methods are required to fill in functionality hole in the base class.

For example, given this class

public abstract class Frobber {
    public abstract void Frob();

    public abstract boolean IsFrobbingNeeded { get; }

    public void FrobUntilFinished() {
        while (IsFrobbingNeeded) {
            Frob();
        }
    }
}

How would you implement this base functionality in a class that has neither Frob() nor IsFrobbingNeeded?

2
  • 1
    An interface can't be instantiated either.
    – Sjoerd
    Commented Jul 21, 2011 at 17:22
  • @Sjoerd: But you need a base class with the shared implementation; that can't be an interface. Commented Jul 21, 2011 at 17:58
1

I am a creator of servlet framework where abstract classes play essential role. I would say more, I need semi abstract methods, when a method needs to be overridden in 50% cases and I would like to see warning from compiler about that method wasn't overridden. I resolve the problem adding annotations. Returning back to your question, there are two different use case of abstract classes and interfaces, and no one is obsolete so far.

0

I don't think they're obsoleted by interfaces, but they might be obsoleted by the strategy pattern.

The primary use of an abstract class is to postpone a part of the implementation; to say, "this part of the class's implementation can be made different".

Unfortunately, an abstract class forces the client to do this via inheritance. Whereas the strategy pattern will allow you to achieve the same result without any inheritance. The client can make instances of your class rather than always defining their own, and the class's "implementation" (behaviour) can vary dynamically. The strategy pattern has the additional plus that behaviour can be changed at run-time, not only at design-time, and also has significantly weaker coupling between the types involved.

0

I've generally faced far, far, more maintenance problems associated with pure interfaces than ABCs, even ABCs used with multiple inheritance. YMMV -- dunno, maybe our team just used them inadequately.

That said, if we use a real world analogy, how much use is there for pure interfaces completely devoid of functionality and state? If I use USB as an example, that's a reasonably stable interface (I think we're at USB 3.2 now, but it has also maintained backwards compatibility).

Yet it's not a stateless interface. It's not devoid of functionality. It's more like an abstract base class than a pure interface. It's actually closer to a concrete class with very specific functional and state requirements, with the only abstraction being what plugs into the port being the only substitutable part.

Otherwise it would just be a "hole" in your computer with a standardized form factor and much looser functional requirements which wouldn't do anything on its own until every manufacturer came up with their own hardware to make that hole do something, at which point it becomes a much weaker standard and nothing more than a "hole" and a specification of what it should do, but no central provision for how to do it. Meanwhile we might end up with 200 different ways to do it after all hardware manufacturers try to come up with their own ways to attach functionality and state to that "hole".

And at that point we might have certain manufacturers that introduce different problems over others. If we need to update the specification we might have 200 different concrete USB port implementations with totally different ways of tackling the specification having to be updated and tested. Some manufacturers might develop de facto standard implementations they share amongst themselves (your analogical base class implementing that interface), but not all. Some versions might be slower than others. Some might have better throughput but worse latency or vice versa. Some might use more battery power than others. Some might flake out and not work with all hardware that's supposed to work with USB ports. Some might require a nuclear reactor to be attached to operate which has a tendency to give its users radiation poisoning.

And that's what I've found, personally, with pure interfaces. There might be some cases where they make sense, like just to model the form factor of a motherboard against a CPU case. Form factor analogies are, indeed, pretty much stateless and devoid of functionality, as with the analogical "hole". But I often consider it a huge mistake for teams to consider that to be somehow superior in all cases, not even close.

To the contrary, I think far more cases would be solved better by ABCs than interfaces if those are the two choices unless your team is so gigantic that it's actually desirable to have the analogical above equivalent of 200 competing USB implementations rather than one central standard to maintain. In a former team I was in, I actually had to fight hard just to loosen up the coding standard to allow ABCs and multiple inheritance, and mainly in response to these maintenance problems described above.

Not the answer you're looking for? Browse other questions tagged or ask your own question.