views:

208

answers:

8

After reading the most excellent book "Head First Design Patterns", I began proselytizing to my colleagues the benefits of patterns and design principles. While extolling the virtues of my favorite pattern - Strategy Pattern - I was asked a question which gave me pause. Strategy, of course, uses inheritance and composition and I was on one of my tirades about "program to an interface (or supertype) not an implementation", when a colleague asked "why use an abstract base class instead of a concrete class?".
I could only come up with "well you force your subclasses to implement abstract methods and prevent them from instantiating the ABC". But to be honest the question caught me off gaurd. Are these the only benefits of using an abstract base class over a concrete class at the top of my hierarchy?

+1  A: 

Yes, although you could also use an interface to force a class to implement specific methods.

Another reason for using an abstract class as opposed to a concrete class is that an abstract class obviously can't be instantiated. Sometimes you also wouldn't want this to happen, so an abstract class is the way to go.

Danny Drogt
A: 

Is there a specific example or problem you're trying to solve with this? I think it's far too rigid to say that you should always use one or the other. Different situations call for different designs.

matt b
+15  A: 

If you need specific methods to be implemented, then use an Interface. If there is shared logic that can be pulled out, use an abstract base class. If the base set of functionality is complete on its own, then you can use a concreate class as the base. An abstract base class, and an Interface cannot be instantiated directly, and that is one of the advantages. If you can use a concrete type, then you need to do override methods, and that has a "code smell" to it.

NerdFury
+1. Great run down of what to use and when.
Chris Lively
Huh? Why would method overriding smell?
ladenedge
Code with virtual methods is much harder to change in the future without breaking some implied behavioral contract. So in .NET they decided that making a method overridable has to be a conscious decision and should be carefully considered. So any overridable method without instructions for the implementor is a "code smell".
Jonathan Allen
If you have a class, and you code the behaivior a certain way. Then later, inherit from that class, and decide that you want to change the behavoir, IMO, there is a smell to that. I think a developer should refactor to a behavior contract (either an interface, or abstract base class) and create two concrete implmentations that have explicit defined reasons for existing. Having an abstract base class, or an interface makes extension more explicit in how to change or replace behavior. Overrides feel more like brute force.
NerdFury
+3  A: 

Program to interface, not to implementation has little to do with abstract and concrete classes. Remember the template method pattern? Classes, abstract or concrete, are the implementation details.

And the reason to use abstract classes instead of concrete classes is that you can invoke methods without implementing them, but by leaving them to be implemented to subclasses instead.

Programming to an interface is a different thing - it is defining what your API does, not how it does it. And this is denoted by interfaces.

Note one key difference - you can have protected abstract methods, which means that this is implementation detail. But all interface methods are public - part of the API.

Bozho
To add to that, "Program to an implementation" would be doing things like using refelection to access a class's private fields.
Jonathan Allen
A: 

First of all, the Strategy Pattern should almost never be used in modern C#. It is mainly for languages like Java that don't support function pointers, delegates, or first-class functions. You will see it in older versions of C# in interfaces such as IComparer.

As for Abstract Base Class vs. Concrete Class, the answer in Java is always "What works better in this situation?" If your strategies can share code, then by all means let them do so.

Design patterns are not instructions on how to do something. They are ways to categorize things that we have already done.

Jonathan Allen
A: 

If the client relies on "implied behavior contract[s]", it is programmed against an implementation and against unguaranteed behavior. Overriding the method while following the contract only exposes bugs in the client, not causes them.

OTOH, the mistake of assuming contracts that aren't there is less likely to cause problems if the method in question is non-virtual--i.e., overriding it cannot cause problems because it cannot be overridden. Only if the implementation of the original method is changed (while still obeying the contract) can it break the client.

apollodude217
A: 

The question of whether a base class should be abstract or concrete depends IMHO largely on whether a base class object which implemented only behaviors that were common to all objects in the class would be useful. Consider a WaitHandle. Calling "wait" upon it will cause code to block until some condition is satisfied, but there's no common way of telling a WaitHandle object that its condition is satisfied. If one could instantiate a "WaitHandle", as opposed to only being able to instantiate instances of derived types, such an object would have to either never wait, or always wait forever. The latter behavior would be pretty useless; the former might have been useful, but could be achieved almost as well with a statically-allocated ManualResetEvent (I think the latter wastes a few resources, but if it's statically allocated the total resource loss should be trivial).

In many cases, I think my preference would be to use references to an interface rather than to an abstract base class, but provide with the interface a base class which provides a "model implementation". So any place one would use a reference to a MyThing, one would supply a reference to "iMyThing". It may well be that 99% (or even 100%) of iMyThing objects are actually a MyThing, but if someone ever needs to have an iMyThing object which inherits from something else, one could do so.

supercat
+1  A: 

Abstract base classes are usually used in scenarios where the designer wants to force an architectural pattern where certain tasks are to be carried out in the same manner by all the classes while other behaviours are dependent on the subclasses. example:

public abstract class Animal{

public void digest(){

}

public abstract void sound(){

}
}

public class Dog extends Animal{
public void sound(){
    System.out.println("bark");
}
}

Stratergy pattern asks designers to use Compositional behaviour for cases where there are families of alogirthms for a behaviour.

frictionlesspulley