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
Method1
e sostituisceMethod2
deve ripetere la convalida dell'argomento. - nel caso in cui lo sviluppatore della classe base decida di aggiungere qualcosa intorno alla parte personalizzabile
Method1
oMethod2
successiva, 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 ProtectedAbstractOrVirtual
classe 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 Stream
classe 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.
virtual
consente l'override facoltativo. Il tuo metodo dovrebbe probabilmente essere pubblico, perché potrebbe non essere ignorato. Fare metodiabstract
ti costringe a scavalcarli; probabilmente dovrebbero esserloprotected
, perché non sono particolarmente utili in unpublic
contesto.