In C#/.NET, I have a class that I want to provide extension points for. I can do this either using inheritance:
public class Animal {
public virtual void Speak() { }
}
public class Dog : Animal {
public overrides void Speak() => Console.WriteLine("Woof");
}
var dog = new Dog();
dog.Speak();
Or using passed-in delegates:
public class Animal {
private Action speak;
public Animal(Action speak) => this.speak = speak;
public void Speak() => speak();
}
var dog = new Animal(() => Console.WriteLine("Woof"));
dog.Speak();
I can already see some differences between them:
- Access to the base behavior -- if via inheritance, the overriding method can choose whether to invoke the base method or not; if via delegates, there is no automatic access to the base behavior.
- Can there be no behavior? -- if via inheritance, there is always some behavior at
Speak
, either the base class behavior, or the derived class behavior. When using delegates, the delegate field could potentially containnull
(although with nullable reference types, this shouldn't happen). - Explicit definition of scoped data / members -- When extending via inheritance, other members or data defined in the derived class are explicitly defined as being part of a class. When using delegates together with lambda expressions, lambda expressions can access the surrounding scope, but the parts of that scope aren't necessarily explicitly defined as such (e.g. closed-over variables).
When is it appropriate to expose extension points via inheritance, and when is it appropriate to use delegates?