NotDesignedForExtension

NotDesignedForExtension

Summary

A class must be designed for inheritance, or else be prohibited from it.

Default severity

Warning

Description

This is something like the C# version of DesignForExtension check of Checkstyle[1]. This rule reports diagnostic information of classes that have a non-empty overridable method or property as follows:

  • The virtual method which is public or protected and implementation of which is not empty
  • The virtual property which is public or protected

This rule prevents the fragile base class problem [2]. And it also prevents Call Super [2], neutralizing a call to the overridden method of the base class, that is, invoking base.Method(...) in C#.

Code fix

The code fix is not provided. Refactor the virtual method to be empty or abstract one, for example, using the Template Method Pattern [3]. And then, change the override method (this is, the method overriding the method of the base class) to be sealed, or change the class to be sealed.

Example

Diagnostic

public class BaseClass
{
    // A virtual method must be empty or be changed to be abstract.
    public virtual void Method()
    {
        DoSomething();
    }
}

public class DerivedClass : BaseClass
{
    // An overriding method must be sealed or empty.
    public override void Method()
    {
        PerformAnotherAction();
    }
}

See also

  • DesignForExtension [1]

    Rationale: This library design style protects superclasses against being broken by subclasses. The downside is that subclasses are limited in their flexibility, in particular they cannot prevent execution of code in the superclass, but that also means that subclasses cannot corrupt the state of the superclass by forgetting to call the superclass's method.

  • Fragile base class [2]

    The fragile base class problem is a fundamental architectural problem of object-oriented programming systems where base classes (superclasses) are considered “fragile” because seemingly safe modifications to a base class, when inherited by the derived classes, may cause the derived classes to malfunction. The programmer cannot determine whether a base class change is safe simply by examining in isolation the methods of the base class.

  • Call super [2]

    Call super is a code smell or anti-pattern of some object-oriented programming languages. Call super is a design pattern in which a particular class stipulates that in a derived subclass, the user is required to override a method and call back the overridden function itself at a particular point. The overridden method may be intentionally incomplete, and reliant on the overriding method to augment its functionality in a prescribed manner. However, the fact that the language itself may not be able to enforce all conditions prescribed on this call is what makes this an anti-pattern.

References

[1] Checkstyle

[2] Wikipedia

[3] Gamma, E. and Helm, R. and Johnson, R. and Vlissides, J. Design Patterns: Elements of Reusable Object-Oriented Software. Reading, Mass: Addison-Wesley, 1994.