Dans les années 2000, un de mes collègues m'a dit que c'était un anti-modèle de rendre les méthodes publiques virtuelles ou abstraites.
Par exemple, il a considéré une classe comme celle-ci pas bien conçue:
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
}
}
Il a déclaré que
- le développeur d'une classe dérivée qui implémente
Method1
et substitueMethod2
doit répéter la validation de l'argument. - dans le cas où le développeur de la classe de base décide d'ajouter quelque chose autour de la partie personnalisable de
Method1
ouMethod2
plus tard, il ne peut pas le faire.
Au lieu de cela, mon collègue a proposé cette approche:
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
}
}
Il m'a dit que rendre les méthodes publiques (ou propriétés) virtuelles ou abstraites est aussi mauvais que rendre les champs publics. En encapsulant des champs dans des propriétés, vous pouvez intercepter ultérieurement tout accès à ces champs, si nécessaire. La même chose s'applique aux membres publics virtuels / abstraits: les envelopper comme indiqué dans la ProtectedAbstractOrVirtual
classe permet au développeur de la classe de base d'intercepter tous les appels qui vont aux méthodes virtuelles / abstraites.
Mais je ne vois pas cela comme une directive de conception. Même Microsoft ne le suit pas: jetez un œil à la Stream
classe pour le vérifier.
Que pensez-vous de cette ligne directrice? Cela a-t-il un sens ou pensez-vous que cela complique trop l'API?
protected
est plus utile lorsque vous souhaitez exposer des membres privés de la classe abstraite à des classes dérivées. En tout cas, je ne suis pas particulièrement préoccupé par l'opinion de votre ami; choisissez le modificateur d'accès qui convient le mieux à votre situation particulière.
virtual
permet la substitution facultative. Votre méthode devrait probablement être publique, car elle pourrait ne pas être remplacée. Créer des méthodesabstract
vous oblige à les ignorer; ils devraient probablement l'êtreprotected
, car ils ne sont pas particulièrement utiles dans unpublic
contexte.