Pregunta

    

Esta pregunta ya tiene una respuesta aquí:

    
            
  •              Diferencia entre sombras y anulando en C #?                                      5 respuestas                          
  •     
    

Estoy un poco confundido acerca anulando vs ocultar un método en C #. usos prácticos de cada uno también serían apreciados, así como una explicación para cuando se podría usar cada uno.

Me gustaría saber anulando - ¿por qué dispositivo? Lo que he aprendido hasta ahora es que por overring podemos proporcionar implementación deseada a un método de una clase derivada, sin cambiar la firma.

Si no anular el método de la superclase y hago cambios en el método de la subclase, la voluntad, que modifican el método de superclase?

También estoy confundido acerca de lo siguiente: -? Lo que demuestra esto

class A
{
    virtual m1()
    {
        console.writeline("Bye to all");
    }
}

class B : A
{
    override m1()
    {
        console.writeLine("Hi to all");
    }
}

class C
{
    A a = new A();
    B b = new B();
    a = b; (what is this)
    a.m1(); // what this will print and why?

    b = a; // what happens here?
}
¿Fue útil?

Solución

Considere lo siguiente:

public class BaseClass
{
  public void WriteNum()
  {
    Console.WriteLine(12);
  }
  public virtual void WriteStr()
  {
    Console.WriteLine("abc");
  }
}

public class DerivedClass : BaseClass
{
  public new void WriteNum()
  {
    Console.WriteLine(42);
  }
  public override void WriteStr()
  {
    Console.WriteLine("xyz");
  }
}
/* ... */
BaseClass isReallyBase = new BaseClass();
BaseClass isReallyDerived = new DerivedClass();
DerivedClass isClearlyDerived = new DerivedClass();

isReallyBase.WriteNum(); // writes 12
isReallyBase.WriteStr(); // writes abc
isReallyDerived.WriteNum(); // writes 12
isReallyDerived.WriteStr(); // writes xyz
isClearlyDerived.WriteNum(); // writes 42
isClearlyDerived.writeStr(); // writes xyz

primordial es la manera clásica OO en el que una clase derivada puede tener un comportamiento más específico que una clase base (en algunos idiomas que no hay más remedio que hacerlo). Cuando un método virtual se llama en un objeto, entonces la versión más derivada del método se llama. Por lo tanto, a pesar de que estamos tratando con isReallyDerived como BaseClass continuación, se utiliza la funcionalidad definida en DerivedClass.

medios

Ocultación de que tenemos un método completamente diferente. Cuando llamamos WriteNum() en isReallyDerived entonces no hay manera de saber que hay un WriteNum() diferente en DerivedClass por lo que no se conoce. Sólo puede ser llamado cuando estamos tratando con el objeto como a DerivedClass.

La mayor parte del tiempo es malo escondite. Por lo general, ya sea que usted debe tener un método como virtual si su probabilidad de ser cambiado en una clase derivada, y anularlo en la clase derivada. Sin embargo, hay dos cosas que es útil para:

  1. Compatibilidad hacia adelante. Si DerivedClass tenía un método DoStuff(), y más tarde BaseClass fue cambiado para agregar un método DoStuff(), (recuerde que pueden ser escritos por diferentes personas y existen en diferentes montajes), entonces la prohibición de escondite miembro habría repente hecha con errores DerivedClass sin ella cambiando. Además, si el nuevo DoStuff() en BaseClass era virtual, a continuación, hacer automáticamente que el DerivedClass una anulación de los que podría conducir al método preexistente que se llama cuando no debe. Por lo tanto, es bueno que escondite es el valor predeterminado (usamos new para que quede claro que definitivamente desea ocultar, pero dejando fuera cueros y emite una advertencia en la compilación).

  2. covarianza del pobre hombre. Considere un método Clone() en BaseClass que devuelve un nuevo BaseClass que es una copia de la creada. En la anulación de DerivedClass esto creará un DerivedClass pero devolverlo como una BaseClass, que no es tan útil. Lo que podríamos hacer es tener un CreateClone() protegido virtual que está anulado. En BaseClass tenemos un Clone() que devuelve el resultado de esto - y todo está bien - en DerivedClass escondemos esto con una nueva Clone() que devuelve un DerivedClass. Llamando Clone() en BaseClass siempre devolverá una referencia BaseClass, que será un valor o un valor BaseClass DerivedClass según corresponda. Llamando Clone() en DerivedClass devolverá un valor DerivedClass, que es lo que nos gustaría en ese contexto. Hay otras variantes de este principio, sin embargo hay que señalar que todos ellos son bastante raros.

Una cosa importante a nota con el segundo caso, es que hemos utilizado precisamente para esconderse Eliminar sorprende al código de llamada, ya que la persona que utiliza DerivedClass podría esperar razonablemente su Clone() para devolver un DerivedClass . Los resultados de cualquiera de las formas en que se podría llamar se mantienen coherentes entre sí. La mayoría de los casos de ocultar sorpresas riesgo de introducir, por lo que generalmente son mal vistas. Esto se justifica precisamente porque resuelve el problema que se esconde a menudo introduce.

En total, esconderse a veces es necesario, con poca frecuencia útil, pero generalmente mal, así que mucho cuidado con él.

Otros consejos

primordial es cuando se proporciona una nueva aplicación override de un método en una clase descendiente cuando se defina ese método en la clase base como virtual.

Ocultación es cuando se proporciona una nueva implementación de un método en una clase descendiente cuando ese método es no definido en la clase base como virtual, o cuando su nueva aplicación no especifica override.

de ocultación es muy a menudo mal; por lo general debe tratar de no hacerlo si se puede evitar en absoluto. Escondite puede causar cosas inesperadas que suceden, porque los métodos ocultos sólo se utilizan cuando se le llama en una variable del tipo real que ha definido, no si se utiliza una referencia de clase de base ... por otro lado, los métodos virtuales, que son anulados va a terminar con la versión correcta método se llama, incluso cuando llama usando la referencia de la clase base en una clase de niño.

Por ejemplo, considere estas clases:

public class BaseClass
{
  public virtual void Method1()  //Virtual method
  {
    Console.WriteLine("Running BaseClass Method1");
  }
  public void Method2()  //Not a virtual method
  {
    Console.WriteLine("Running BaseClass Method2");
  }
}
public class InheritedClass : BaseClass
{
  public override void Method1()  //Overriding the base virtual method.
  {
    Console.WriteLine("Running InheritedClass Method1");
  }
  public new void Method2()  //Can't override the base method; must 'new' it.
  {
    Console.WriteLine("Running InheritedClass Method2");
  }
}

llamada de Let como este, con una instancia de InheritedClass, en una referencia a juego:

InheritedClass inherited = new InheritedClass();
inherited.Method1();
inherited.Method2();

Esto devuelve lo que debe esperar; ambos métodos dicen que se están ejecutando las versiones InheritedClass.

  

Running InheritedClass Método1
  Correr InheritedClass Método2

Este código crea una instancia de la misma, InheritedClass, pero lo almacena en una referencia BaseClass:

BaseClass baseRef = new InheritedClass();
baseRef.Method1();
baseRef.Method2();

Normalmente, bajo los principios de programación orientada a objetos, que debe esperar el mismo resultado que el ejemplo anterior. Pero no obtiene el mismo resultado:

  

Running InheritedClass Método1
  Correr BaseClass Método2

Cuando escribió el código InheritedClass, que puede haber querido todas las llamadas a Method2() para ejecutar el código que escribió en ella. Normalmente, esto sería cómo funciona - suponiendo que se está trabajando con un método virtual que ha anulado. Pero debido a que está utilizando un método new / oculta, llama a la versión de la referencia que está utilizando, en su lugar.


Si ese es el comportamiento que realmente quieren y, a continuación; Hay que ir. Pero me gustaría sugerir fuertemente que si eso es lo que quiere, puede haber un problema de arquitectura más grande con el código.

Método primordial es override simpley una implementación por defecto de un método de la clase base en la clase derivada.

Método de ocultación: Se puede hacer uso de la 'nueva' palabra clave antes de un método virtual en una clase derivada

como

class Foo  
{  
  public virtual void foo1()  
  {  

  }  
}  

class Bar:Foo  
{  
  public new virtual void foo1()  
  {   

  }  
}  

Ahora si haces otra clase Bar1 que se deriva de barra, puede anular foo1 que es defind en Bar.

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