Abstract Class Design
- DO NOT define public or protected-internal constructors in abstract types.
- Constructors should be public only if users will need to create instances of the type. Because you cannot create instances of an abstract type, an abstract type with a public constructor is incorrectly designed and misleading to the users.(This also applies to protected-internal constructors.)
// bad design
public abstract class Claim {
public Claim (int number) {
}
}
// good design
public abstract class Claim {
// incorrect Design
protected Claim (int number) {
}
}
- DO define a protected or an internal constructor on abstract classes.
- A protected constructor is more common and simply allows the base class to do its own initialization when subtypes are created.
public abstract class Claim {
protected Claim() {
}
}
An internal constructor can be used to limit concrete implementations of the abstract class to the assembly defining the class.
public abstract class Claim {
internal Claim() {
}
}
| BRAD ABRAMS
|
| Many languages (such as C#) will insert a protected constructor if you do not. It is a good practice to define the constructor explicitly in the source so that it can be more easily documented and maintained over time.
|
- DO provide at least one concrete type that inherits from each abstract class that you ship.
- This helps to validate the design of the abstract class. For example,
System.IO.FileStream is an implementation of the System.IO.Stream abstract class.
| BRAD ABRAMS
|
| I have seen countless examples of a "well-designed" base class or interface where the designers spent hundreds of hours debating and tweaking the design only to have it blown out of the water when the first real-world client came to use the design. Far too often these real-world clients come too late in the product cycle to allow time for the correct fix. Forcing yourself to provide at least one concrete implementation reduces the chances of finding a new problem late in the product cycle.
|