早在2000年代,我的一位同事就告诉我,将公共方法虚拟化或抽象化是一种反模式。
例如,他认为这样的课程设计得不好:
public abstract class PublicAbstractOrVirtual
{
public abstract void Method1(string argument);
public virtual void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
// default implementation
}
}
他说
- 实现
Method1
并重写的派生类的开发人员Method2
必须重复参数验证。 - 如果基类的开发人员决定在
Method1
或Method2
以后的可自定义部分周围添加一些内容,他将无法执行。
相反,我的同事提出了这种方法:
public abstract class ProtectedAbstractOrVirtual
{
public void Method1(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method1Core(argument);
}
public void Method2(string argument)
{
if (argument == null) throw new ArgumentNullException(nameof(argument));
this.Method2Core(argument);
}
protected abstract void Method1Core(string argument);
protected virtual void Method2Core(string argument)
{
// default implementation
}
}
他告诉我,将公共方法(或属性)虚拟化或抽象化与使字段公开一样糟糕。通过将字段包装到属性中,可以在以后需要时拦截对该字段的任何访问。这同样适用于公共虚拟/抽象成员:以ProtectedAbstractOrVirtual
类中所示的方式包装它们,使基类开发人员可以拦截对虚拟/抽象方法的所有调用。
但是我不认为这是设计准则。甚至Microsoft也没有遵循它:只需看一看Stream
该类即可验证这一点。
您如何看待该指导方针?这有意义吗,还是您认为API过于复杂?
protected
当您要将抽象类的私有成员公开给派生类时,这是最有用的。无论如何,我并不特别关注您朋友的意见;选择最适合您的特定情况的访问修饰符。
virtual
允许可选的覆盖。 您的方法可能应该是公共的,因为它可能不会被覆盖。制作方法abstract
迫使您覆盖它们。它们可能应该是protected
,因为它们在public
上下文中不是特别有用。