Cuando creamos una clase que hereda de una clase abstracta y cuando implementamos la clase abstracta heredada, ¿por qué tenemos que usar la palabra clave de anulación?
public abstract class Person
{
public Person()
{
}
protected virtual void Greet()
{
// code
}
protected abstract void SayHello();
}
public class Employee : Person
{
protected override void SayHello() // Why is override keyword necessary here?
{
throw new NotImplementedException();
}
protected override void Greet()
{
base.Greet();
}
}
Dado que el método se declara abstracto en su clase principal, no tiene ninguna implementación en la clase principal, entonces, ¿por qué es necesaria la anulación de palabras clave aquí?
new
palabra clave '... También obtendrá el error" ningún método anula el método de la clase base ".Respuestas:
"¿Por qué?" preguntas como esta pueden ser difíciles de responder porque son vagas. Asumiré que su pregunta es "¿qué argumentos podrían hacerse durante el diseño del lenguaje para argumentar la posición de que
override
se requiere la palabra clave ?"Comencemos dando un paso atrás. En algunos lenguajes, digamos, Java, los métodos son virtuales por defecto y se anulan automáticamente. Los diseñadores de C # eran conscientes de esto y lo consideraban un defecto menor en Java. C # no es "Java con las partes estúpidas extraídas" como algunos han dicho, pero los diseñadores de C # estaban ansiosos por aprender de los puntos problemáticos de diseño de C, C ++ y Java, y no replicarlos en C #.
Los diseñadores de C # consideraron la anulación como una posible fuente de errores; después de todo, es una forma de cambiar el comportamiento del código existente y probado , y eso es peligroso. La anulación no es algo que deba hacerse de manera casual o accidental; debe ser diseñado por alguien que lo piense mucho . Es por eso que los métodos no son virtuales de manera predeterminada, y por qué debe decir que está anulando un método.
Ese es el razonamiento básico. Ahora podemos entrar en un razonamiento más avanzado.
La respuesta de StriplingWarrior da un buen primer corte al hacer un argumento más avanzado. El autor de la clase derivada puede estar desinformado acerca de la clase base, puede tener la intención de crear un nuevo método y no debemos permitir que el usuario anule por error .
Aunque este punto es razonable, hay una serie de argumentos en contra, como:
Entonces hagamos un argumento aún más avanzado sobre este punto. ¿En qué circunstancias se puede excusar al autor de una clase derivada por no saber qué hace la clase base? Bueno, considere este escenario:
Lo que queremos que suceda es que el autor de D es informado de que algo relevante ha cambiado . Lo relevante que ha cambiado es que M es ahora un requisito y que su implementación debe sobrecargarse. Es posible que DM necesite cambiar su comportamiento una vez que sepamos que podría llamarse desde la clase base. Lo correcto es no decir en silencio "oh, DM existe y extiende BM". Lo correcto para el compilador es fallar y decir "oye, autor de D, revisa esta suposición que ya no es válida y arregla tu código si es necesario".
En su ejemplo, supongamos que el
override
era opcional enSayHello
porque es reemplazar un método abstracto. Hay dos posibilidades: (1) el autor del código tiene la intención de anular un método abstracto, o (2) el método de anulación se anula por accidente porque alguien más cambió la clase base, y el código ahora está mal de alguna manera sutil. No podemos distinguir estas posibilidades sioverride
es opcional .Pero si
override
es necesario , podemos distinguir tres escenarios. Si hay un posible error en el código, a continuaciónoverride
se faltante . Si se anula intencionalmente, entoncesoverride
está presente . Y si es intencional no anulando entoncesnew
es presente . El diseño de C # nos permite hacer estas sutiles distinciones.Recuerde que los informes de errores del compilador requieren leer la mente del desarrollador ; el compilador debe deducir del código incorrecto qué código correcto probablemente tenía el autor en mente , y dar un error que los señala en la dirección correcta. Cuantas más pistas podamos hacer que el desarrollador deje en el código lo que estaban pensando, mejor será el trabajo que el compilador puede hacer al informar errores y, por lo tanto, más rápido podrá encontrar y corregir sus errores.
Pero, en general, C # fue diseñado para un mundo en el que el código cambia . De hecho, hay una gran cantidad de características de C # que parecen "extrañas" porque informan al desarrollador cuando una suposición que solía ser válida se volvió inválida porque cambió una clase base. Esta clase de errores se llama "fallas de clase base frágiles", y C # tiene una serie de mitigaciones interesantes para esta clase de falla.
fuente
Es para especificar si está intentando anular otro método en la clase principal o crear una nueva implementación única para este nivel de la jerarquía de clases. Es concebible que un programador no sea consciente de la existencia de un método en una clase principal con exactamente la misma firma que el creado en su clase, lo que podría generar sorpresas desagradables.
Si bien es cierto que un método abstracto debe anularse en una clase secundaria no abstracta, los creadores de C # probablemente sintieron que aún es mejor ser explícito sobre lo que está tratando de hacer.
fuente
Debido a que el
abstract
método es un método virtual sin implementación, según la especificación del lenguaje C # , significa que el método abstracto es implícitamente un método virtual. Yoverride
se usa para extender o modificar la implementación abstracta o virtual, como puede ver aquíPara reformularlo un poco, utiliza métodos virtuales para implementar algún tipo de enlace tardío, mientras que los métodos abstractos obligan a las subclases del tipo a anular explícitamente el método. Ese es el punto, cuando el método es
virtual
, puede ser anulado, cuando es unabstract
- debe ser anuladofuente
Para agregar a la respuesta de @ StriplingWarrior, creo que también se hizo para tener una sintaxis que sea consistente con la anulación de un método virtual en la clase base.
Por lo tanto, C # podría haber sido diseñado para que no necesitara la palabra clave de anulación para anular métodos abstractos, pero creo que los diseñadores decidieron que sería confuso ya que no sería coherente con anular un método virtual.
fuente
override
? Creo que la mayoría de la gente estaría de acuerdo en que es absurdo obligar al autor de D a hacer un cambio de código innecesario; su clase esta bien!