C # diseño: ¿Por qué se requiere nueva / anulación de métodos abstractos, pero no en los métodos virtuales?

StackOverflow https://stackoverflow.com/questions/3634529

Pregunta

¿Por qué es nuevo / anulación requerida en los métodos abstractos, pero no en los métodos virtuales?

Muestra 1:

abstract class ShapesClass
{
    abstract public int Area(); // abstract!
}

class Square : ShapesClass
{
    int x, y;

    public int Area() // Error: missing 'override' or 'new'
    {
        return x * y;
    }
}

El compilador mostrará este error: Para hacer que el miembro actual de anulación que la aplicación, añadir la palabra clave override. De lo contrario, añadir la nueva palabra clave

Ejemplo 2:

class ShapesClass
{
    virtual public int Area() { return 0; } // it is virtual now!
}

class Square : ShapesClass
{
    int x, y;

    public int Area() // no explicit 'override' or 'new' required
    {
        return x * y;
    }
}

Esto compilará bien, ocultando el método por defecto.

comprendo perfectamente las diferencias técnicas. Sin embargo, me pregunto por qué el lenguaje fue diseñado de esa manera. ¿No sería mejor tener la misma restricción en la "Muestra 2" también? Es decir, en la mayoría de los casos si se crea un método con el mismo nombre que en la clase padre, que por lo general la intención de anularlo. Así que creo que indica explícitamente Sustituir / Nueva tendría sentido en métodos virtuales también.

¿Hay una razón En cuanto al diseño de este comportamiento?

Actualización: La segunda muestra realmente causa una advertencia. El primer ejemplo muestra un error porque se requiere la subclase para implementar el método abstracto. No vi la advertencia en VS .. hace perfectamente sentido para mí ahora. Gracias.

¿Fue útil?

Solución

El uso de cualquiera de los C # 3.0 compilador como enviado en .NET 3.5 SP1, o el compilador de C # 4.0 como enviado en .NET 4.0, me sale el siguiente error para su primer ejemplo:

  

error CS0534: 'ConsoleApplication3.Square' no implementa miembro abstracta heredada 'ConsoleApplication3.ShapesClass.Area ()'

Y el siguiente Advertencia para el segundo:

  

advertencia CS0114: 'ConsoleApplication3.Square.Area ()' cueros miembro heredado 'ConsoleApplication3.ShapesClass.Area ()'. Para hacer que el miembro actual de anulación que la aplicación, añadir la palabra clave override. De lo contrario, añadir la nueva palabra clave.

En el primer caso se trata de un error, ya que no está realmente reemplazando el método de base, lo que significa que no hay aplicación para el método abstracto en una clase concreta. En el segundo caso se trata de una advertencia porque el código es técnicamente correcto, pero el compilador sospecha que no es lo que quería decir. Esta es una de las razones es generalmente una buena idea para que las "advertencias tratan como errores" ajuste de compilación.

Así que no puedo repro su comportamiento, y el comportamiento de las miradas del compilador bien para mí. ¿Qué versión del compilador está usando?

Otros consejos

Aquí está la respuesta directamente de la especificación C #.

  

... ocultar un nombre de acceso desde una   alcance heredado provoca una advertencia para ser   informó. En el ejemplo

class Base
{
    public void F() {}
}
class Derived: Base
{
    public void F() {}      // Warning, hiding an inherited name
}
  

la declaración de F en causas derivados   una advertencia que se informa. un escondite   nombre heredado no es específicamente una   de error, ya que ello impediría   evolución separada de clases base.   Por ejemplo, el anterior podría situación   han surgido porque una tarde   versión de Base introdujo un método F   que no estaba presente en una anterior   versión de la clase. Tenía el anteriormente   situación ha sido un error, entonces cualquier   cambio realizado en una clase base en una   biblioteca de clases versionado por separado   potencialmente podría causar derivada   clases para ser válidas. La advertencia   causada por ocultar un nombre puede heredado   ser eliminado a través del uso de la nueva   modificador:

class Base
{
    public void F() {}
}
class Derived: Base
{
    new public void F() {}
}
  

El nuevo modificador indica que el F   en Derivado es “nuevo”, y que es   de hecho la intención de ocultar el heredada   miembro.

La diferencia es que el método abstracto tiene que ser reemplazado, pero la virtual no lo hace.

Es un error para heredar la clase abstracta (en una clase no abstracta) sin poner en práctica todos los miembros abstractas, sino que sólo te dan una advertencia cuando se hereda de la clase sin especificar override o new para el método virtual.

Creo que en la primera forma se obtiene el error de compilación, porque el método abstracto se oculta y no se han aplicado (de modo eficaz su clase está mal, y que sería difícil de averiguar por qué). En el segundo caso se obtiene solamente una advertencia, porque la clase es utilizable.

de versiones

A primera vista, se puede pensar que esconderse método no parece particularmente útil. Hay una situación donde es posible que necesite usarlo, sin embargo. Digamos que usted desea utilizar una clase llamada MotorVehicle que fue escrito por otro programador, y desea utilizar esta clase para derivar su propia clase. Más lejos, Supongamos también que desea definir un método Accelerate() en su clase derivada. Por ejemplo:

public class Car : MotorVehicle
{
    // define the Accelerate() method
    public void Accelerate()
    {
        Console.WriteLine(“In Car Accelerate() method”);
        Console.WriteLine(model + “ accelerating”);
    }
}

A continuación, vamos a suponer que el otro programador más adelante modifica la clase y decide MotorVehicle añadir su propio método virtual Accelerate():

public class MotorVehicle
{
    // define the Accelerate() method
    public virtual void Accelerate()
    {
        Console.WriteLine(“In MotorVehicle Accelerate() method”);
        Console.WriteLine(model + “ accelerating”);
    }
}

La adición de este método Accelerate() por la otra programador causa un problema: La Método Accelerate() en sus pieles clase Car el método heredado Accelerate() ahora se define en MotorVehicle su clase. Más tarde, cuando se llega a compilar su clase Car, no está claro que el compilador ya sea que realmente se refiere a su método para ocultar el método heredado. Debido a esto, la compilador informa de la siguiente advertencia cuando intenta compilar su clase Car:

  

advertencia CS0114: ‘Car.Accelerate ()’ cueros heredan miembro   ‘MotorVehicle.Accelerate ()’. Para hacer que la corriente de anulación miembro de que se   aplicación, añadir la palabra clave override. De lo contrario, añadir la nueva palabra clave.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top