Одна вещь, которую предыдущие решения игнорируют, заключается в том, что ImplementClass может переопределить MethodToBeCalled и не вызывать MustBeCalled -
public abstract class AbstractClass
{
public abstract void AbstractMethod();
private void MustBeCalled()
{
//will be invoked by MethodToBeCalled();
Console.WriteLine("AbstractClass.MustBeCalled");
}
public void MethodToBeCalled()
{
MustBeCalled();
AbstractMethod();
}
}
public class ImplementClass : AbstractClass
{
public override void AbstractMethod()
{
Console.WriteLine("ImplementClass.InternalAbstractMethod");
}
public new void MethodToBeCalled() {
AbstractMethod();
}
}
Если бы только C # позволял запечатывать не переопределенные методы - как последнее ключевое слово Java!
Единственный способ преодолеть это - использовать делегирование, а не наследование, поскольку классы можно определить как закрытые. И я использую пространство имен и «внутренний» модификатор доступа, чтобы предотвратить предоставление новой реализации для реализации классов. Кроме того, метод для переопределения должен быть определен как защищенный, иначе пользователи могут вызывать его напрямую.
namespace Something
{
public sealed class OuterClass
{
private AbstractInnerClass inner;
public OuterClass(AbstractInnerClass inner)
{
this.inner = inner;
}
public void MethodToBeCalled()
{
MustBeCalled();
inner.CalledByOuter();
}
public void MustBeCalled()
{
//this must be called when AbstractMethod is invoked
System.Console.WriteLine("OuterClass.MustBeCalled");
}
}
public abstract class AbstractInnerClass
{
internal void CalledByOuter()
{
AbstractMethod();
}
protected abstract void AbstractMethod();
}
}
public class ImplementInnerClass : Something.AbstractInnerClass
{
protected override void AbstractMethod()
{
//when called, base.MustBeCalled() must be called.
//how can i enforce this?
System.Console.WriteLine("ImplementInnerClass.AbstractMethod");
}
public new void CalledByOuter()
{
System.Console.WriteLine("doesn't work");
}
}