12

I recently had to update an abstract base class on some OSS that I was using so that it was more testable by making them virtual (I could not use an interface as it combined two). This got me thinking whether I should mark all of the methods that I needed virtual, or if I should mark every public method/property virtual. I generally agree with Roy Osherove that every method should be made virtual, but I came across this article that got me thinking about whether this was necessary or not. I am going to limit this down to abstract classes for simplicity, however (whether all concrete public methods should be virtual is especially debatable, I am sure).

I could see where you might want to allow a sub-class to use a method, but not want it overriding the implementation. However, as long as you trust that Liskov's Substitution Principle will be followed, then why would you not allow it to be overriden? By marking it abstract, you are forcing a certain override anyway, so, it seems to me that all public methods inside of an abstract class should indeed be marked virtual.

However, I wanted to ask in case there was something I might not be thinking. Should all public methods within an abstract class be made virtual?

2

5 Answers 5

9

However, as long as you trust that Liskov's Substitution Principle will be followed, then why would you not allow it to be overriden?

For example, because I want the skeleton implementation of an algorithm to be fixed, and only allow specific parts to be (re)defined by subclasses. This is widely known as the Template Method pattern (emphasis below by me):

The template method thus manages the larger picture of task semantics, and more refined implementation details of selection and sequence of methods. This larger picture calls abstract and non-abstract methods for the task at hand. The non-abstract methods are completely controlled by the template method but the abstract methods, implemented in subclasses, provide the pattern's expressive power and degree of freedom. Some or all of the abstract methods can be specialized in a subclass, allowing the writer of the subclass to provide particular behavior with minimal modifications to the larger semantics. The template method (which is non-abstract) remains unchanged in this pattern, ensuring that the subordinate non-abstract methods and abstract methods are called in the originally-intended sequence.

Update

Some concrete examples of projects I have been working on:

  1. communicating with a legacy mainframe system via various "screens". Each screen has a bunch of fields, of fixed name, position and length, containing specific data bits. A request fills up certain fields with specific data. A response returns data in one or more other fields. Each transaction follows the same basic logic, but the details are different on every screen. We used Template Method in several different projects to implement the fixed skeleton of the screen handling logic, while allowing subclasses to define the screen-specific details.
  2. exporting / importing configuration data in DB tables to/from Excel files. Again, the basic schema of processing an Excel file and inserting/updating DB records, or dumping the records to Excel is the same for each table, but the details of each table are different. So Template Method is a very obvious choice to eliminate code duplications and make the code easier to understand and maintain.
  3. Generating PDF documents. Each document has the same structure, but their content is different each time, depending on lots of factors. Again, Template Method makes it easy to separate the fixed skeleton of the generation algorithm from the case-specific, changeable details. In fact. it even applies on multiple levels here, as the document consists of several sections, each of which consists of zero or more fields. Template Method is applied on 3 distinct levels here.

In the first two cases, the original legacy implementation used Strategy, resulting in lots of duplicated code, which of course over the years grew subtle differences here and there, contained lots of duplicated or slightly different bugs, and was very difficult to maintain. Refactoring to Template Method (and some other enhancements, like using Java annotations) reduced code size by about 40-70%.

These are only the most recent examples which come to my mind. I could cite more cases from almost every project I have been working on so far.

2
  • Simply quoting the GoF is not an answer. You'd need to give an actual reason to do such a thing.
    – DeadMG
    Apr 15, 2012 at 23:02
  • @DeadMG, I have been using Template Method regularly during my career, so I thought it was obvious that it is a very practical and useful pattern (as most of the GoF patterns are... these aren't theoretical academical exercises, but collected from real world experience). But apparently not everyone agrees with it... so I add a couple of concrete examples to my answer. Apr 16, 2012 at 8:33
2

It's perfectly reasonable, and sometimes desirable to have non-virtual methods in an abstract base class; just because it's an abstract class doesn't necessarily mean every part of it should be usable polymorphically.

For example, you might want to use the 'Non virtual polymorphism' idiom, whereby a function is called polymorphically from a non-virtual member function, in order to ensure that certain preconditions or postconditions are met before the virtual function is called

class MyAbstractBaseClass
{
protected:
    virtual void OverrideMe() = 0;
public:
    void CallMeFirst();

    void CallMe()
    {
        CallMeFirst();
        OverrideMe();
    }
};
1
  • I would argue that, as long as the overall behavior remains the same, then this could be made virtual. You could fill the pre/post conditions using a different implementation (database vs in-memory). Otherwise, it should be a private function? Apr 15, 2012 at 21:03
2

It is enough for a class to contain ONE virtual method, in order for the class to become abstract. You might want to pay attention to which methods you want virtual and which not, according to the type of polymorphism you're planning to use.

1

Ask yourself what the use is of a non-virtual method in an abstract class. Such a method would have to have an implementation to make it useful. But if the class has an implementation, can it still be called an abstract class? Even if the language/compiler allows it, does it make sense? Personally, I don't think so. You would have a normal class with abstract methods that descendants are expected to implement.

My primary language is Delphi, not C#. In Delphi, if you mark a method abstract, you also have to mark it virtual or the compiler complains. Haven't followed the latest language changes too closely, but if abstract classes are in or would come to Delphi, I would expect the compiler to complain about any non-virtual methods, any private methods and about any method implementations for a class marked abstract at the class level.

6
  • 2
    I think it makes perfect sense to have an abstract class that has some abstract methods, some virtual methods and some non-virtual methods. I think it always depends on what exactly do you want to do.
    – svick
    Apr 15, 2012 at 20:06
  • 3
    First I will go over your C# q's. An abstract method in C# is implicitly virtual and cannot have an implementation. As to your first point, an abstract class in C# can, and should have an implementation of some sort (otherwise you should just use an interface). The point of a class being abstract is that it MUST be subclassed, however it contains logic that (theoretically) all subclasses will use. This cuts down on code duplication. What I am asking is whether any of those implementations should be closed off from being overriden (essentially saying the base way is the only way). Apr 15, 2012 at 20:06
  • @JustinPihony: thanks. In Delphi, when you mark a method abstract, the compiler will complain if you provide an implementation for it. Interesting how different languages implement concepts differently and thus create different expectations in their users. Apr 16, 2012 at 5:58
  • @svick: yes it does make perfect sense, I just wouldn't call it an abstract class, but a class with abstract methods... But I guess that may just be my interpretation. Apr 16, 2012 at 6:16
  • @MarjanVenema, but that's not terminology C# uses. If you mark any methods in a class abstract, you must also mark the whole class abstract.
    – svick
    Apr 16, 2012 at 12:03
0

However, as long as you trust that Liskov's Substitution Principle will be followed, then >why would you not allow it to be overriden?

You don't make certain methods virtual because you don't believe this to be the case. Further, by making certain methods not virtual, you're signaling to inheritors what method(s) should be implemented.

Personally, I will often make method overloads that exist for convenience not virtual so that users of the class can have consistent defaults and implementers aren't even able to make the error of breaking that implied behavior.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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