In den 2000er Jahren sagte mir ein Kollege, es sei ein Anti-Pattern, öffentliche Methoden virtuell oder abstrakt zu machen.
Zum Beispiel hielt er eine Klasse wie diese für nicht gut designt:
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
}
}
Das hat er gesagt
- Der Entwickler einer abgeleiteten Klasse, die implementiert
Method1und überschreibt,Method2muss die Argumentvalidierung wiederholen. - Falls der Entwickler der Basisklasse beschließt, etwas um den anpassbaren Teil von
Method1oderMethod2später hinzuzufügen , kann er dies nicht tun.
Stattdessen schlug mein Kollege diesen Ansatz vor:
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
}
}
Er sagte mir, dass es genauso schlimm ist, öffentliche Methoden (oder Eigenschaften) virtuell oder abstrakt zu machen, wie Felder öffentlich zu machen. Wenn Sie Felder in Eigenschaften einschließen, können Sie bei Bedarf den Zugriff auf diese Felder später abfangen. Dasselbe gilt für öffentliche virtuelle / abstrakte Member: Wenn diese wie in der ProtectedAbstractOrVirtualKlasse gezeigt verpackt werden, kann der Basisklassenentwickler alle Aufrufe abfangen, die an die virtuellen / abstrakten Methoden gesendet werden.
Aber ich sehe das nicht als Designrichtlinie. Selbst Microsoft folgt dem nicht: Schauen Sie sich die StreamKlasse an, um dies zu überprüfen.
Was halten Sie von dieser Richtlinie? Ergibt es irgendeinen Sinn oder denken Sie, dass es die API überkompliziert?
protectedist besonders nützlich, wenn Sie private Mitglieder der abstrakten Klasse abgeleiteten Klassen aussetzen möchten. Auf jeden Fall bin ich nicht besonders besorgt über die Meinung Ihres Freundes; Wählen Sie den Zugriffsmodifikator, der für Ihre spezielle Situation am sinnvollsten ist.
virtualermöglicht optionales Überschreiben. Ihre Methode sollte wahrscheinlich öffentlich sein, da sie möglicherweise nicht überschrieben wird. Wenn Sie Methodenabstracterstellen, müssen Sie diese überschreiben. Sie sollten es wahrscheinlich seinprotected, weil sie in einempublicKontext nicht besonders nützlich sind .