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
Method1
und überschreibt,Method2
muss die Argumentvalidierung wiederholen. - Falls der Entwickler der Basisklasse beschließt, etwas um den anpassbaren Teil von
Method1
oderMethod2
spä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 ProtectedAbstractOrVirtual
Klasse 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 Stream
Klasse an, um dies zu überprüfen.
Was halten Sie von dieser Richtlinie? Ergibt es irgendeinen Sinn oder denken Sie, dass es die API überkompliziert?
protected
ist 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.
virtual
ermöglicht optionales Überschreiben. Ihre Methode sollte wahrscheinlich öffentlich sein, da sie möglicherweise nicht überschrieben wird. Wenn Sie Methodenabstract
erstellen, müssen Sie diese überschreiben. Sie sollten es wahrscheinlich seinprotected
, weil sie in einempublic
Kontext nicht besonders nützlich sind .