En la década de 2000, un colega mío me dijo que es un antipatrón hacer que los métodos públicos sean virtuales o abstractos.
Por ejemplo, consideró que una clase como esta no está bien diseñada:
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
}
}
Él dijo que
- El desarrollador de una clase derivada que implementa
Method1
y anulaMethod2
tiene que repetir la validación del argumento. - en caso de que el desarrollador de la clase base decida agregar algo alrededor de la parte personalizable
Method1
oMethod2
posterior, no puede hacerlo.
En cambio, mi colega propuso este enfoque:
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
}
}
Me dijo que hacer que los métodos públicos (o propiedades) sean virtuales o abstractos es tan malo como hacer públicos los campos. Al envolver los campos en propiedades, uno puede interceptar cualquier acceso a esos campos más adelante, si es necesario. Lo mismo se aplica a los miembros públicos virtuales / abstractos: envolverlos de la manera que se muestra en la ProtectedAbstractOrVirtual
clase permite al desarrollador de la clase base interceptar cualquier llamada que vaya a los métodos virtuales / abstractos.
Pero no veo esto como una guía de diseño. Incluso Microsoft no lo sigue: solo eche un vistazo a la Stream
clase para verificar esto.
¿Qué opinas de esa guía? ¿Tiene algún sentido, o crees que está complicando demasiado la API?
protected
es más útil cuando desea exponer miembros privados de la clase abstracta a clases derivadas. En cualquier caso, no estoy particularmente preocupado por la opinión de tu amigo; elija el modificador de acceso que tenga más sentido para su situación particular.
virtual
permite la anulación opcional. Su método probablemente debería ser público, ya que podría no ser anulado. Hacer métodosabstract
te obliga a anularlos; probablemente deberían serloprotected
, porque no son particularmente útiles en unpublic
contexto.