TLTR:因为开闭原则。
在我看来,为什么使用抽象成员 protected 而不是 public 是为了隐藏“实现细节”。如果要确保在类中定义每个抽象成员的意图,公开一个单一的“入口点”会很方便。通常,公共方法将协调何时以及什么抽象成员被调用或访问,以及在什么特定的顺序和在什么情况下,但是这一层封装的权衡是你失去了可扩展性属性。
说明:
假设我们创建了一个包含多个异常处理程序类的库。
初步实施:
namespace MyLibrary;
public abstract class ExceptionHandlerBase
{
protected abstract void HandleException(Exception ex, Action operation);
public void Execute(Action operation)
{
try {
operation.Invoke();
} catch(Exception ex) {
this.HandleException(ex, operation);
}
}
}
public class InputExceptionHandler: ExceptionHandlerBase
{
protected override void HandleException(Exception ex, Action operation)
{
throw new Exception(
message: "Wrong input" // or whatever...
inner: ex);
}
}
public class DbExceptionHandler : ExceptionHandlerBase
{
protected override void HandleException(Exception ex, Action operation)
{
Console.WriteLine("Failed to connect to database. Retrying...");
operation.Invoke();
}
}
现在,如果我们想扩展 ExceptionHandlerBase 的行为,我们将看到由于 ExceptionHandlerBase.HandleException 方法的 protected 访问修饰符而受到限制。
让我们尝试在ExceptionHandlerBase.HandleException方法之前添加一个钩子:
class ExceptionHandlerWrapper : ExceptionHandlerBase
{
readonly ExceptionHandlerBase _base;
public ExceptionHandlerWrapper(ExceptionHandlerBase @base)
{
thos._base = @base;
}
protected override void HandleException(Exception ex, Action operation)
{
this.BeforeHandleException();
this._base.HandleException(ex, operation); // Compile error**
}
private void BeforeHandleException()
{
// do additional stuff
}
}
如您所见,存在编译错误,因为无法从定义它的类外部访问ExceptionHandlerBase.HandleException。