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?