When you need a part of the class to be implemented. The best example I've used is the template method pattern.
public abstract class SomethingDoer
{
public void Do()
{
this.DoThis();
this.DoThat();
}
protected abstract void DoThis();
protected abstract void DoThat();
}
Thus, you can define the steps that will be taken when Do() is called, without knowing the specifics of how they will be implemented. Deriving classes must implement the abstract methods, but not the Do() method.
Extensions methods don't necessarily satisfy the "must be a part of the class" part of the equation. Additionally, iirc, extension methods cannot (appear to) be anything but public in scope.
edit
The question is more interesting than I had originally given credit for. Upon further examination, Jon Skeet answered a question like this on SO in favour of using interfaces + extension methods. Also, a potential downside is using reflection against an object hierarchy designed in this way.
Personally, I am having trouble seeing the benefit of altering a currently common practice, but also see few to no downsides in doing it.
It should be noted that it is possible to program this way in many languages via Utility classes. Extensions just provide the syntactic sugar to make the methods look like they belong to the class.
In layman's terms:
Interfaces are for "can do/can be treated as" type of relationships.
Abstract ( as well as concrete ) classes are for "is a" kind of relationship.
Look at these examples:
class Bird extends Animal implements Flight;
class Plane extends Vehicle implements Flight, AccountableAsset;
class Mosquito extends Animal implements Flight;
class Horse extends Animal;
class RaceHorse extends Horse implements AccountableAsset;
class Pegasus extends Horse implements Flight;
Bird
, Mosquito
and Horse
are Animals
. They are related. They inherit common methods from Animal like eat(), metabolize() and reproduce()
. Maybe they override these methods, adding a little extra to them, but they take advantage of the default behavior implemented in Animal like metabolizeGlucose().
Plane
is not related to Bird
, Mosquito
or Horse
.
Flight
is implemented by dissimilar, unrelated classes, like Bird
and Plane
.
AccountableAsset
is also implemented by dissimilar, unrelated classes, like Plane
and RaceHorse
.
Horse
doesn't implement Flight.
As you can see classes (abstract or concrete) helps you build a hierarchies, letting you inhering code from the upper levels to the lower levels of the hierarchy. In theory the lower you are in the hierarchy, the more specialized your behavior is, but you don't have to worry about a lot of things that are already taken care of.
Interfaces, in the other hand, create no hierarchy, but they can help homogenize certain behaviors across hierarchies so you can abstract them from the hierarchy in certain contexts.
For example you can have a program sum the value of a group of AccountableAssets
regardless of their being RaceHorses
or Planes
.
Best Answer
No, this is not possible.
There are two ways to restrict inheritance:
The
final
keyword makes a class impossible to extend. This modifier is forbidden on interfaces, and you want to inherit from it anyway.Package-private visibility means only classes in the same package can inherit from the interface, but the interface itself is not accessible outside the package which makes the interface useless. I.e., you cannot hold an object of any of those subtypes in a variable of type
Bar
. This makes dynamic dispatch (polymorphism) impossible.You can insert a new
AbstractFooBar
that looks like this:Foo
only has binaries available. You cannot addBar
as an interface it implements; nor can you require its subclasses to implementBar
; nor can you restrictBar
so non-Foo
-derived classes cannot inherit from it. This is the closest you can get. If nothing else, this is merely a convenience that imposes no restrictions on the use ofBar
.While this technically answers your question, you may want to take a step back and reconsider exactly what you are trying to accomplish.
Normally when I see a requirement for restricting a type hierarchy in this way it is due to trying to shoehorn inheritance where composition is more appropriate. Both techniques have their places, and it is best not to try to use one where the other is a better fit.