Diferencia entre nuevo y anular


Preguntándose cuál es la diferencia entre lo siguiente:

Caso 1: Clase base

public void DoIt();

Caso 1: Clase heredada

public new void DoIt();

Caso 2: Clase base

public virtual void DoIt();

Caso 2: Clase heredada

public override void DoIt();

Ambos casos 1 y 2 parecen tener el mismo efecto basado en las pruebas que he ejecutado. ¿Hay alguna diferencia, o una forma preferida?

Author: Mateen Ulhaq, 2009-09-09

13 answers

El modificador de anulación se puede utilizar en métodos virtuales y debe ser utilizado en métodos abstractos. Esto indica para el compilador para usar el último definido implementación de un método. Aunque el método se llama en una referencia a la clase base utilizará la implementación que lo anula.

public class Base
{
    public virtual void DoIt()
    {
    }
}

public class Derived : Base
{
    public override void DoIt()
    {
    }
}

Base b = new Derived();
b.DoIt();                      // Calls Derived.DoIt

Llamará a Derived.DoIt si esto reemplaza a Base.DoIt.

El nuevo modificador indica la compilador para usar la implementación de su clase hija en lugar de la clase de padre aplicación. Cualquier código que no sea hacer referencia a su clase pero el padre la clase usará la clase padre aplicación.

public class Base
{
    public virtual void DoIt()
    {
    }
}

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

Base b = new Derived();
Derived d = new Derived();

b.DoIt();                      // Calls Base.DoIt
d.DoIt();                      // Calls Derived.DoIt

Primero llamará Base.DoIt, luego Derived.DoIt. Son efectivamente dos métodos completamente separados que tienen el mismo nombre, en lugar de que el método derivado anule el método base.

Fuente: Microsoft blog

 202
Author: rahul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-17 08:10:56

Virtual: indica que un método puede ser anulada por un heredero

Override: anula la funcionalidad de un método virtual en una clase base, proporcionando una funcionalidad diferente.

Nuevo: oculta el método original (que no tiene que ser virtual), proporcionando una funcionalidad diferente. Esto solo debe usarse cuando sea absolutamente necesario.

Cuando se oculta un método, todavía se puede acceder al método original mediante up casting a la clase base. Esto es útil en algunos escenarios, pero peligroso.

 156
Author: Jon B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-25 08:51:40

En el primer caso está ocultando la definición en la clase padre. Esto significa que solo se invocará cuando esté tratando con el objeto como clase hija. Si envía la clase a su tipo padre, se invocará el método del padre. En la segunda instancia, el método se sobrescribe y se invocará independientemente de si el objeto se castea como clase secundaria o principal.

 14
Author: tvanfosson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-09 11:35:04

Intenta lo siguiente: (case1)

((BaseClass)(new InheritedClass())).DoIt()

Editar: virtual + override se resuelven en tiempo de ejecución (por lo que override realmente anula los métodos virtuales), mientras que new simplemente crea un nuevo método con el mismo nombre, y oculta el antiguo, se resuelve en tiempo de compilación -> su compilador llamará al método que 've'

 7
Author: nothrow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-09 11:34:38

En el caso 1 si utilizas el método DoIt() de la clase heredada mientras el tipo es declarado como la clase base verás la acción de la clase base even.

/* Results
Class1
Base1
Class2
Class2
*/
public abstract class Base1
{
    public void DoIt() { Console.WriteLine("Base1"); }
}
public  class Class1 : Base1 
{
    public new void DoIt() { Console.WriteLine("Class1"); }
}
public abstract class Base2
{
    public virtual void DoIt() { Console.WriteLine("Base2"); }
}
public class Class2 : Base2
{
    public override void DoIt() { Console.WriteLine("Class2"); }
}
static void Main(string[] args)
{
    var c1 = new Class1();
    c1.DoIt();
    ((Base1)c1).DoIt();

    var c2 = new Class2();
    c2.DoIt();
    ((Base2)c2).DoIt();
    Console.Read();
}
 3
Author: Matthew Whited,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-09 11:41:39

La diferencia entre los dos casos es que en el caso 1, el método base DoIt no se anula, solo se oculta. Lo que esto significa es que dependiendo del tipo de la variable depende de qué método se llamará. Por ejemplo:

BaseClass instance1 = new SubClass();
instance1.DoIt(); // Calls base class DoIt method

SubClass instance2 = new SubClass();
instance2.DoIt(); // Calls sub class DoIt method

Esto puede ser muy confuso y resulta en un comportamiento no esperado y debe evitarse si es posible. Así que la forma preferida sería el caso 2.

 3
Author: Shannon Cornish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-05 18:15:02

Mi manera de tener en cuenta ambas palabras clave que son opuestas entre sí.

override: virtual se debe definir la palabra clave para anular el método. El método que usa la palabra clave override que, independientemente del tipo de referencia(referencia de la clase base o clase derivada) si se crea una instancia con la clase base, se ejecuta el método de la clase base. De lo contrario, se ejecuta el método de la clase derivada.

new: si la palabra clave es utilizada por un método, a diferencia de la palabra clave override, el tipo de referencia es importante. Si se crea una instancia con la clase derivada y el tipo de referencia es la clase base, el método de la clase base se ejecuta. Si se crea una instancia con clase derivada y el tipo de referencia es clase derivada, se ejecuta el método de clase derivada. Es decir, es el contraste de la palabra clave override. Al paso, si olvida u omite agregar una nueva palabra clave al método, el compilador se comporta de forma predeterminada como new se usa la palabra clave.

class A 
{
    public string Foo() 
    {
        return "A";
    }

    public virtual string Test()
    {
        return "base test";
    }
}

class B: A
{
    public new string Foo() 
    {
        return "B";
    }
}

class C: B 
{
    public string Foo() 
    {
        return "C";
    }

    public override string Test() {
        return "derived test";
    }
}

Llamar a main:

A AClass = new B();
Console.WriteLine(AClass.Foo());
B BClass = new B();
Console.WriteLine(BClass.Foo());
B BClassWithC = new C();
Console.WriteLine(BClassWithC.Foo());

Console.WriteLine(AClass.Test());
Console.WriteLine(BClassWithC.Test());

Salida:

A
B
B
base test
derived test
 2
Author: snr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-14 12:20:15

Si la palabra clave override se usa en la clase derive, entonces su override el método padre.

Si la palabra clave new se usa en derive class, entonces derive method hided by parent method.

 1
Author: saba,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-12 07:10:12

El siguiente artículo está en vb.net pero creo que la explicación sobre los nuevos vs anulaciones es muy fácil de entender.

Https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides

En algún punto del artículo, hay esta frase:

En general, Shadows asume que la función asociada con el tipo es invocado, mientras que Sobreescribe asume que la implementación del objeto es ejecutar.

La respuesta aceptada a esta pregunta es perfecto, pero creo que este artículo proporciona buenos ejemplos para agregar un mejor significado sobre las diferencias entre estas dos palabras clave.

 1
Author: Samuel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-11 12:52:43

De todos ellos, nuevo es el más confuso. A través de la experimentación, la nueva palabra clave es como dar a los desarrolladores la opción de anular la implementación de la clase heredera con la implementación de la clase base definiendo explícitamente el tipo. Es como pensar al revés.

En el ejemplo siguiente, el resultado devolverá "Resultado derivado" hasta que el tipo se defina explícitamente como prueba de clase base, solo entonces se devolverá "Resultado base".

class Program
{
    static void Main(string[] args)
    {
        var test = new DerivedClass();
        var result = test.DoSomething();
    }
}

class BaseClass
{
    public virtual string DoSomething()
    {
        return "Base result";
    }
}

class DerivedClass : BaseClass
{
    public new string DoSomething()
    {
        return "Derived result";
    }
}
 1
Author: usefulBee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-22 15:55:25

La diferencia funcional no se mostrará en estas pruebas:

BaseClass bc = new BaseClass();

bc.DoIt();

DerivedClass dc = new DerivedClass();

dc.ShowIt();

En este ejemplo, el Doit que se llama es el que usted espera ser llamado.

Para ver la diferencia tienes que hacer esto:

BaseClass obj = new DerivedClass();

obj.DoIt();

Verá si ejecuta esa prueba que en el caso 1 (como lo definió), se llama al DoIt() en BaseClass, en el caso 2 (como lo definió), se llama al DoIt() en DerivedClass.

 0
Author: Ken Falk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-25 14:52:43

Tenía la misma pregunta y es realmente confuso, debe considerar que overridey new palabras clave que funcionan solo con objetos de tipo clase base y valor de clase derivada. En este caso solo verá el efecto de anulación y nuevo: Así que si tienes class A y B, B hereda de A, luego crea una instancia de un objeto como este:

A a = new B();

Ahora los métodos de llamada tomarán en consideración su estado. Override : significa que extiende la función del método, luego usa el método en la clase derivada, mientras que new le dice al compilador que oculte el método en la clase derivada y use el método en la clase base en su lugar. Aquí hay una muy buena vista de ese tema:

Https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-14 09:03:21

En el primer caso llamará al método clase derivada DoIt() porque nueva palabra clave oculta el método clase base DoIt ().

En el segundo caso llamará a overridden DoIt()

  public class A
{
    public virtual void DoIt()
    {
        Console.WriteLine("A::DoIt()");
    }
}

public class B : A
{
    new public void DoIt()
    {
        Console.WriteLine("B::DoIt()");
    }
}

public class C : A
{
    public override void DoIt()
    {
        Console.WriteLine("C::DoIt()");
    }
}

Vamos a crear una instancia de estas clases

   A instanceA = new A();

    B instanceB = new B();
    C instanceC = new C();

    instanceA.DoIt(); //A::DoIt()
    instanceB.DoIt(); //B::DoIt()
    instanceC.DoIt(); //B::DoIt()

Todo se espera arriba. Vamos a establecer instanceB e instanceC a instanceA y llamar al método DoIt () y comprobar el resultado.

    instanceA = instanceB;
    instanceA.DoIt(); //A::DoIt() calls DoIt method in class A

    instanceA = instanceC;
    instanceA.DoIt();//C::DoIt() calls DoIt method in class C because it was overriden in class C
 0
Author: cimey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-22 07:20:23