Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

If we assume that it is not desirable for the base class to be a pure interface class, and using the 2 examples from below, which is a better approach, using the abstract or virtual method class definition?

  • The advantage of "abstract" version is that it is probably looks cleaner and forces the derived class to give a hopefully meaningful implementation.

  • The advantage of the "virtual" version is that it can be easily pulled in by other modules and used for testing without adding a bunch of underlying framework like the abstract version requires.

Abstract Version:

public abstract class AbstractVersion
{
    public abstract ReturnType Method1();        
    public abstract ReturnType Method2();
             .
             .
    public abstract ReturnType MethodN();

    //////////////////////////////////////////////
    // Other class implementation stuff is here
    //////////////////////////////////////////////
}

Virtual Version:

public class VirtualVersion
{
    public virtual ReturnType Method1()
    {
        return ReturnType.NotImplemented;
    }

    public virtual ReturnType Method2()
    {
        return ReturnType.NotImplemented;
    }
             .
             .
    public virtual ReturnType MethodN()
    {
        return ReturnType.NotImplemented;
    }

    //////////////////////////////////////////////
    // Other class implementation stuff is here
    //////////////////////////////////////////////
}
share|improve this question
    
Why are we assuming an interface is not desirable? –  Anthony Pegram Feb 26 '13 at 17:54
    
Without a partially problem, it's hard to say one is better than the other. –  Codism Feb 26 '13 at 17:55
    
@Anthony: An Interface is not desirable because there is useful functionality that will also go into this class. –  Dunk Feb 26 '13 at 19:18
3  
return ReturnType.NotImplemented? Seriously? If you can't reject unimplemented type at compile time (you can; use abstract methods) at least throw an exception. –  Jan Hudec Feb 27 '13 at 12:06
3  
@Dunk: Here they are necessary. Return values will go unchecked. –  Jan Hudec Feb 28 '13 at 14:27

4 Answers 4

up vote 11 down vote accepted

My vote, if I were consuming your stuff, would be for the abstract methods. That goes along with "fail early." It may be a pain at declaration time to add all methods (though any decent refactoring tool will do this quickly), but at least I know what the problem is immediately and fix it. I'd rather that than be debugging 6 months and 12 people's worth of changes later to see why we're suddenly getting a not implemented exception.

share|improve this answer
    
Good point regarding unexpectantly getting the NotImplemented error. Which is a plus on the abstract side, because you'll get a compile-time instead of run-time error. –  Dunk Feb 26 '13 at 19:43
3  
+1 - In addition to failing early, inheritors can see immediately what methods they need to implement via "Implement Abstract Class" rather than doing what they thought was enough and then failing at runtime. –  Telastyn Feb 26 '13 at 22:02
    
I accepted this answer because failing at compile time was a plus that I failed to list and because of the reference to using the IDE to auto implement the methods quickly. –  Dunk Feb 28 '13 at 14:17

The virtual version is both bug prone and semantically incorrect.

Abstract is saying "this method isn't implemented here. you must implement it to make this class work"

Virtual is saying "I have a default implementation but you can change me if you need"

If your ultimate objective is testability then interfaces are normally the best option. (this class does x rather than this class is a x). You might need to break your classes into smaller components though for this to work nicely.

share|improve this answer

This depends on the usage of your class.

If the methods have some reasonable “empty” implementation, you have lots of methods and you often override just a few of them, then using virtual methods makes sense. For example ExpressionVisitor is implemented this way.

Otherwise, I think you should use abstract methods.

Ideally, you shouldn't have methods that are not implemented, but in some cases, that is the best approach. But if you decide to do that, such methods should throw NotImplementedException, not return some special value.

share|improve this answer
    
I would note that "NotImplementedException" often indicates an error of omission, whereas "NotSupportedException" indicates an overt choice. Other than that, I agree. –  Anthony Pegram Feb 26 '13 at 22:26

I would suggest that you reconsider having a separate interface defined which your base class implements, and then you follow the abstract approach.

Imaging code like this:

public interface IVersion
{
    ReturnType Method1();        
    ReturnType Method2();
             .
             .
    ReturnType MethodN();
}

public abstract class AbstractVersion : IVersion
{
    public abstract ReturnType Method1();        
    public abstract ReturnType Method2();
             .
             .
    public abstract ReturnType MethodN();

    //////////////////////////////////////////////
    // Other class implementation stuff is here
    //////////////////////////////////////////////
}

Doing this solves these problems:

  1. By having all code that uses objects derived from AbstractVersion can now be implemented to receive IVersion interface instead, This means that they can be more easily unit tested.

  2. Release 2 of your product can then implement an interface IVersion2 to provide additional functionality without breaking your existing customers code.

eg.

public interface IVersion
{
    ReturnType Method1();        
    ReturnType Method2();
             .
             .
    ReturnType MethodN();
}

public interface IVersion2
{
    ReturnType Method2_1();
}

public abstract class AbstractVersion : IVersion, IVersion2
{
    public abstract ReturnType Method1();        
    public abstract ReturnType Method2();
             .
             .
    public abstract ReturnType MethodN();
    public abstract ReturnType Method2_1();

    //////////////////////////////////////////////
    // Other class implementation stuff is here
    //////////////////////////////////////////////
}

It's also worth reading up about dependency inversion as well, to prevent this class from containing hard coded dependencies that prevent effective unit testing.

share|improve this answer
    
I upvoted for providing the ability to handle different versions. However, I've tried and tried again to make effective use of interface classes, as a normal part of design and always end up realizing that the interface classes either provides no/little value and actually obsfuscates the code instead of making life easier. It is very seldom that I would have multiple classes inherit from another, like an interface class, and there isn't a fair amount of commonality that isn't shareable. Abstract classes tend to work better as I get the built in shareable aspect that interfaces dont provide. –  Dunk Jan 22 at 15:16
    
And using inheritance with good class names provides a much more intuitive way to easily understand the classes (and thus the system) than a bunch of functional interface class names that are difficult to tie together mentally as a whole. Also, using interface classes tends to create a ton of extra classes, making the system harder to understand in yet another way. –  Dunk Jan 22 at 15:36

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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