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
Method1y anulaMethod2tiene 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
Method1oMethod2posterior, 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 ProtectedAbstractOrVirtualclase 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 Streamclase para verificar esto.
¿Qué opinas de esa guía? ¿Tiene algún sentido, o crees que está complicando demasiado la API?
protectedes 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.
virtualpermite la anulación opcional. Su método probablemente debería ser público, ya que podría no ser anulado. Hacer métodosabstractte obliga a anularlos; probablemente deberían serloprotected, porque no son particularmente útiles en unpubliccontexto.