2009-09-09 16 views
134

Se pregunta cuál es la diferencia entre lo siguiente:diferencia entre el nuevo y anular

Caso 1: Clase base

public void DoIt(); 

Caso 1: clase heredada

public new void DoIt(); 

Caso 2: base de la Clase

public virtual void DoIt(); 

Caso 2: clase heredada

public override void DoIt(); 

Tanto el caso 1 y 2 parecen tener el mismo efecto sobre la base de las pruebas que se han topado. ¿Hay alguna diferencia, o una forma preferida?

+2

duplicados de muchas preguntas, incluyendo http://stackoverflow.com/questions/159978/c-keyword-usage-virtualoverride-vs-new –

Respuesta

170

El modificador override se puede utilizar en métodos virtuales y debe ser utilizado en métodos abstractos. Esto indica que el compilador utiliza la última implementación definida de un método. Incluso si se llama al método en una referencia a , la clase base utilizará la implementación anulándola.

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án Derived.DoIt si eso anula Base.DoIt.

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

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, entonces Derived.DoIt. Son efectivamente dos métodos completamente separados que tienen el mismo nombre, en lugar del método derivado que reemplaza el método base.

Fuente: Microsoft blog

+4

'Esto indica que el compilador utilice la última aplicación definida de una método'. ¿Cómo se puede encontrar la última implementación definida de un método? – AminM

+5

Comience desde una clase concreta, verifique si tiene una implementación del método de interés. Si lo hace, terminaste. Si no lo hace, vaya un paso arriba en la jerarquía de herencia, es decir, verifique si la súper clase tiene el método de interés. Continúe hasta que haya encontrado el método de interés. – csoltenborn

7

intento siguiente: (Caso 1)

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

edición: + anulación virtuales se resuelven en tiempo de ejecución (de modo anular realmente anula métodos virtuales), mientras que el nuevo acaba de crear un nuevo método con el mismo nombre, y oculta la edad , se resuelve en tiempo de compilación -> su compilador llamará al método que 've'

13

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

149

virtual: indica que un método puede ser anulado por una heredera

override: anula la funcionalidad de un método virtual en una clase base, que proporciona una funcionalidad diferente.

nuevos: cueros el método original (que no tiene por qué ser virtual), que proporciona una funcionalidad diferente. Esto solo debe usarse donde sea absolutamente necesario.

Cuando oculta un método, puede seguir accediendo al método original mediante conversión ascendente a la clase base. Esto es útil en algunos escenarios, pero peligroso.

+0

¿Por qué es peligroso usar un método que oculta el método base? ¿O está insinuando que el lanzamiento de machos en general es peligroso? – Mark

+1

@Mark: una persona que llama puede no estar al tanto de la implementación y causar un uso indebido accidental. –

3

La diferencia entre los dos casos es que en el caso 1, el método base DoIt no se anula, simplemente 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 realmente confuso y da como resultado un comportamiento no esperado y debe evitarse si es posible. Entonces la forma preferida sería el caso 2.

3

En el caso 1, si usó llamar al método DoIt() de la clase heredada, mientras que el tipo se declara como la clase base, verá la acción de la clase base incluso.

/* 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(); 
} 
+0

Usted tuerca muestra como un token inválido cuando pruebo su código – Learner

+0

Podría publicar la advertencia o el error que está recibiendo. Este código funcionó bien cuando originalmente lo publiqué. –

+0

Todo esto debe pegarse dentro de su clase de punto de entrada (Programa). Eso fue eliminado para permitir un mejor formato en este sitio. –

1

Si la palabra clave override se utiliza en clase derivan entonces su anulación el método de los padres.

Si se utiliza la palabra clave new en la clase derivada, derive el método oculto por el método principal.

0

La diferencia funcional no será mostrada en estas pruebas:

BaseClass bc = new BaseClass(); 

bc.DoIt(); 

DerivedClass dc = new DerivedClass(); 

dc.ShowIt(); 

En este exmample, el Doit que se llama es el que se puede esperar a ser llamado.

Con el fin de ver la diferencia que tienes que hacer esto:

BaseClass obj = new DerivedClass(); 

obj.DoIt(); 

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

0

que tenían la misma pregunta y es muy confuso, debe tener en cuenta que anulación y nuevas palabras clave trabajar sólo con los objetos de la clase base tipo y valor de clase derivada.En este caso sólo se verá el efecto de anulación y nueva: Así que si usted tiene class A y B, B hereda de A, a continuación, crear una instancia de un objeto como éste:

A a = new B(); 

Ahora en métodos de llamada se llevará su estado en consideración. Anular: significa que amplía la función del método, luego usa el método en la clase derivada, mientras que nuevo le dice al compilador que oculte el método en la clase derivada y use el método en la clase base. Aquí es una muy buena vista a ese tema:

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

1

Mi manera de tener en cuenta tanto las palabras clave que son opuestos el uno del otro.

override: virtual se debe definir la palabra clave para anular el método. El método que utiliza la palabra clave override independientemente del tipo de referencia (referencia de la clase base o de la 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 clase derivada y el tipo de referencia es clase base, se ejecuta el método de clase base. Si se instancia con clase derivada y el tipo de referencia es clase derivada, se ejecuta el método de clase derivada. A saber, es el contraste de la palabra clave override. En passant, si olvida u omite agregar una palabra clave nueva al método, el compilador se comporta de manera predeterminada como se usa la palabra clave new.

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"; 
    } 
} 

de llamadas en el principal:

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 
1

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

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

En algún momento en el artículo, no es esta frase:

En general, las sombras asume la función asociada con el tipo se invoca , mientras anulaciones asume la implementación del objeto es ejecutado.

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

-1

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

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

+0

Agregue su comentario si se opone. Golpear y correr es tan cobarde. – usefulBee

0

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

En el segundo caso se llamará a overriden 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 instancia de estas clases se espera

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 a arriba. Deje set instanceB y instanceC a instanceA y llame al método DoIt() y verifique 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 
Cuestiones relacionadas