¿Por qué los métodos virtuales deben anularse explícitamente en C#?¿Por qué los métodos virtuales deben anularse explícitamente en C#?
Respuesta
Al declarar un método como virtual
, usted está indicando su intención que el método se puede reemplazar en una clase derivada.
Al declarar su método de ejecución como override
, su son indicando su intención que está sustituyendo un método virtual
.
Al requerir que se utilice la palabra clave override
para anular un método virtual, los diseñadores del lenguaje fomentan la claridad, al exigirle que exprese sus intenciones.
Porque hace que el código sea más legible:
class Derived : Base
{
void Foo();
}
En C++, Foo puede o no ser un método virtual, no podemos decir mirando a la definición. En C#, sabemos que un método es virtual (o no lo es) porque hay una palabra clave virtual o de anulación.
El comentario de Jason a continuación es una mejor respuesta.
(editado para mayor claridad)
... y le da a Intellisense la capacidad de ayudarnos a anular un método. Escriba "anular" e Intellisense aparece con una opción e incluso completa la firma de método completa para nosotros. ¿Qué tan maravilloso es eso? – Tergiver
... y, lo que es más importante, permite que el compilador nos diga cuándo cometemos un error (por ejemplo, si agrega un parámetro al método de clase base en C++, rompe todas las clases derivadas pero no tiene forma de saberlo) - una causa de algunos realmente desagradables para rastrear errores, porque los bits del comportamiento de la clase derivada simplemente dejan de funcionar silenciosamente. En C# da un error por cada anulación que ya no anula nada) –
_ "En C++ podría ser, podemos" Dígalo mirando la definición. "_ - Al observar la definición, podemos decir que no es C++ en absoluto. – stakx
Si no agrega la palabra clave override
, el método estará oculto (como si tuviera la palabra clave new
), no se anula.
Por ejemplo:
class Base {
public virtual void T() { Console.WriteLine("Base"); }
}
class Derived : Base {
public void T() { Console.WriteLine("Derived"); }
}
Base d = new Derived();
d.T();
Este código imprime Base
. Si agrega override
a la implementación Derived
, el código se imprimirá Derived
.
No puede hacer esto en C++ con un método virtual. (There is no way to hide a C++ virtual method without overriding it)
No se deben anular todos los métodos virtuales, aunque todos los métodos abstractos deberían (y deben) serlo. En cuanto a por qué la palabra clave 'anular' es explícita, es porque la anulación y la ocultación se comportan de manera diferente. Un método de ocultación no se llama a través de una referencia a una clase base, mientras que un método reemplazado sí lo es. Esta es la razón por la que el compilador advierte específicamente sobre cómo debe usar la palabra clave 'nueva' en el caso en que se oculta en lugar de anularla.
Es porque los miembros del equipo C# son todos programadores expertos en C++. Y sepa cuán incipiente es esta falla en particular:
class Base {
protected:
virtual void Mumble(int arg) {}
};
class Derived : public Base {
protected:
// Override base class method
void Mumble(long arg) {}
};
Es mucho más común de lo que pueda pensar. La clase derivada siempre se declara en otro archivo de código fuente. Normalmente no se equivoca al momento, sucede cuando se refactoriza. El código no funciona, el código funciona bastante normal, simplemente no hace lo que espera que haga. Puedes mirarlo por una hora o un día y no ver el error.
Esto nunca puede suceder en un programa C#. Incluso C++ administrado adoptó esta sintaxis, rompiendo intencionalmente con la sintaxis nativa de C++. Siempre una elección valiente. IntelliSense quita el aguijón a la verborrea extra.
Hay muchos ajustes de sintaxis en C# que se parecen a este tipo de sintaxis de prevención de errores.
EDIT: y el resto de la comunidad C++ acordó y aprobó la anulación palabra clave en la nueva especificación del lenguaje C++ 11.
+1 La mejor respuesta IMO porque explica el "por qué" detrás de la decisión del diseño del lenguaje en lugar de "cómo funcionan las llamadas virtuales", como lo hacen las respuestas con una calificación más alta ... PS. @Hans, parece que estoy tropezando con muchas respuestas pertinentes escritas por ti estos días :) –
No hay necesidad de anular explícitamente un método virtual en una clase derivada. Marcar un método virtual solo habilita la anulación.
- 1. ¿Los métodos que implementan métodos virtuales puros de una clase de interfaz deben declararse también virtuales?
- 2. ¿Qué son los métodos virtuales?
- 3. ¿Cómo funcionan los métodos virtuales en C#?
- 4. ¿Métodos virtuales puros en C#?
- 5. ¿Por qué las funciones virtuales en C++ se llaman 'virtuales'?
- 6. ¿Por qué los métodos parciales deben ser anulados?
- 7. métodos virtuales puros C++
- 8. java @SafeVarargs por qué los métodos privados deben ser finales
- 9. Métodos o eventos virtuales en C#
- 10. ¿Por qué deben definirse los métodos de extensión C# en clases estáticas?
- 11. ¿Los métodos abstractos son virtuales?
- 12. Mocking métodos no virtuales en C#
- 13. ¿Por qué los métodos de interfaz C# no se declaran abstractos o virtuales?
- 14. Tablas de métodos virtuales
- 15. ¿Por qué los tipos WinRT deben sellarse?
- 16. Comparación: métodos de interfaz vs métodos virtuales vs métodos abstractos
- 17. Métodos no virtuales en Java
- 18. C++ - ¿Uso excesivo de métodos virtuales?
- 19. Alternativa a C++ estática métodos virtuales
- 20. falso/simulacro de métodos no virtuales C++
- 21. C# métodos estáticos virtuales (o abstractos)
- 22. métodos no virtuales Sustitución
- 23. Impacto del rendimiento de los métodos virtuales
- 24. Funciones virtuales en constructores, ¿por qué los idiomas son diferentes?
- 25. ¿Por qué usar funciones virtuales?
- 26. Clonación clase C++ con métodos virtuales puros
- 27. Anulación de métodos virtuales calificados
- 28. ¿Por qué escribir explícitamente "privado"?
- 29. ¿Por qué los métodos estáticos deben ser incluidos en una clase?
- 30. por qué los métodos de extensión en C# Class Libraries
¿Por qué no marcarlo como 'abstracto' y forzar la anulación? –
@George: Porque solo puedes usar el modificador abstracto en clases abstractas. –
@George Stocker - Porque es posible que no desee marcar toda su clase como abstracta (la clase necesita que el modificador abstracto tenga métodos abstractos). –