Negli anni 2000 un mio collega mi ha detto che è un anti-schema rendere virtuali o astratti i metodi pubblici.
Ad esempio, ha considerato una classe come questa non ben progettata:
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
}
}
Lo ha affermato
- lo sviluppatore di una classe derivata che implementa
Method1e sostituisceMethod2deve ripetere la convalida dell'argomento. - nel caso in cui lo sviluppatore della classe base decida di aggiungere qualcosa intorno alla parte personalizzabile
Method1oMethod2successiva, non può farlo.
Invece il mio collega ha proposto questo approccio:
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
}
}
Mi ha detto che rendere i metodi (o le proprietà) pubblici virtuali o astratti è negativo quanto rendere pubblici i campi. Se si racchiudono i campi in proprietà, è possibile intercettare qualsiasi accesso a tali campi in un secondo momento, se necessario. Lo stesso vale per i membri pubblici virtuali / astratti: il loro avvolgimento come mostrato nella ProtectedAbstractOrVirtualclasse consente allo sviluppatore della classe base di intercettare tutte le chiamate che vanno ai metodi virtuali / astratti.
Ma non lo vedo come una linea guida di progettazione. Anche Microsoft non lo segue: dai un'occhiata alla Streamclasse per verificarlo.
Cosa ne pensi di quella linea guida? Ha senso o pensi che stia complicando eccessivamente l'API?
protectedè molto utile quando si desidera esporre membri privati della classe astratta a classi derivate. In ogni caso, non sono particolarmente preoccupato per l'opinione del tuo amico; scegli il modificatore di accesso che ha più senso per la tua situazione particolare.
virtualconsente l'override facoltativo. Il tuo metodo dovrebbe probabilmente essere pubblico, perché potrebbe non essere ignorato. Fare metodiabstractti costringe a scavalcarli; probabilmente dovrebbero esserloprotected, perché non sono particolarmente utili in unpubliccontesto.