c# - method - Diferencia exacta entre anular y ocultar
virtual c# (9)
Al ocultar un método o una propiedad, simplemente indica que desea evitar que dicho método sea polimórfico cuando tiene un objeto de ese tipo. Además, los métodos ocultos se llaman de una forma no polimórfica, por lo que llamar a este tipo de método se debe conocer en tiempo de compilación, ya que se trata simplemente de un método no virtual.
¿Puede alguien decir el funcionamiento de la anulación y la ocultación en términos de memoria y referencias.
class A
{
public virtual void Test1() { //Impl 1}
public virtual void Test2() { //Impl 2}
}
class B : A
{
public override void Test1() { //Impl 3}
public new void Test2() { Impl 4}
}
static Main()
{
A aa=new B() //This will give memory to B
aa.Test1(); //What happens in terms of memory when this executes
aa.Test2(); //-----------------------SAME------------------------
}
Aquí la memoria está con la clase B, pero en la segunda instrucción se llamará aa.Test2 método de la clase A. ¿Por qué es? Si B tiene memoria, entonces debe llamarse al método de B (en mi opinión).
Cualquier enlace / ejercicio que describa este fundamental muy profunda y completamente será de gran ayuda.
Deduciendo del código provisto, debe tener B:A
Puede ocultar un método en caso de que desee crear su propia implementación del método (por ejemplo) de la clase base, que no puede anularse, porque, por ejemplo, no es virtual
.
En mi experiencia, solía esconderme principalmente para debug
.
Por ejemplo, cuando no sé quién establece la propiedad de algún component
3rd prt, el código no está disponible para mí. Entonces, lo que hago es:
- crear una clase hija del componente
- ocultar la propiedad de interés con
new
palabra clave - poner el punto de ruptura en
set
- y espera cuando sea golpeado.
A veces, es muy útil y me ayuda a obtener información de manera rápida, especialmente en la primera etapa cuando estás aprendiendo nuevos components
, frameworks
, libraries
... lo que sea.
En pocas palabras, al anular un método o propiedad, el método de anulación debe tener la misma firma que el método base. Al ocultar esto no es necesario, el nuevo objeto puede tomar cualquier forma como se muestra a continuación
// base
public int GrossAmount { get; set; }
// hiding base
public new string GrossAmount
{
get;
set;
}
El método Test1 () en la clase A y el método test1 () en la clase B se ejecutará de acuerdo con MethdOverriding .
El método Test2 () en la clase A y el método test2 () en la clase B se ejecutará de acuerdo con la ocultación del método .
En el método Overriding, los miembros de la clase infantil se ejecutarán, y en Método se ocultará el método Ocultar a los miembros de la clase Parent.
public class BaseClass
{
public void PrintMethod()
{
Console.WriteLine("Calling base class method");
}
}
public class ChildClass
{
public new void PrintMethod()
{
Console.WriteLine("Calling the child or derived class method");
}
}
class Program
{
static void Main()
{
BaseClass bc = new ChildClass();
bc.PrintMethod();
}
}
La ocultación del método es aquella cuando la variable de referencia de la clase base apunta a un objeto de clase hijo. Invocará el método oculto en la clase base.
Donde como, cuando declaramos método virtual en la clase base. Anulamos ese método en la clase derivada o secundaria. Entonces la variable de referencia de la clase base llamará al método de clase derivado. Esto se llama Anulación de método.
Eche un vistazo a esta respuesta a otra pregunta de Eric Lippert.
Parafraseando (hasta los límites de mi comprensión), estos métodos entran en "ranuras". A
tiene dos ranuras: una para Test1
y otra para Test2
.
Como A.Test1
está marcado como virtual
y B.Test1
está marcado como override
, la implementación de Test1
de Test1
no crea su propia ranura sino que sobrescribe la implementación de A
Ya sea que trate una instancia de B
como B
o la eleve a una A
, la misma implementación se encuentra en esa ranura, por lo que siempre obtendrá el resultado de B.Test1
.
Por el contrario, dado que B.Test2
se marca como new
, crea su propia ranura. (Como lo haría si no se marcara como new
pero se le dio un nombre diferente.) La implementación de Test2
de Test2
todavía está "allí" en su propio espacio; ha sido escondido en lugar de sobrescrito. Si trata una instancia de B
como B
, obtiene B.Test2
; si lo A.Test2
a una A
, no puedes ver la nueva ranura, y se llama a A.Test2
.
Para agregar a la respuesta de @ Rawling , se pueden mostrar ejemplos prácticos usando un ejemplo como este:
class Base
{
// base property
public virtual string Name
{
get { return "Base"; }
}
}
class Overriden : Base
{
// overriden property
public override string Name
{
get { return "Overriden"; }
}
}
class New : Base
{
// new property, hides the base property
public new string Name
{
get { return "New"; }
}
}
1. Anulación
En el caso de la propiedad modificada , la ranura del método virtual de la clase base se reemplaza por una implementación diferente. El compilador ve el método como virtual y debe resolver su implementación durante el tiempo de ejecución utilizando la tabla virtual del objeto.
{
Base b = new Base();
Console.WriteLine(b.Name); // prints "Base"
b = new Overriden();
// Base.Name is virtual, so the vtable determines its implementation
Console.WriteLine(b.Name); // prints "Overriden"
Overriden o = new Overriden();
// Overriden.Name is virtual, so the vtable determines its implementation
Console.WriteLine(o.Name); // prints "Overriden"
}
2. Ocultar
Cuando un método o una propiedad se oculta con la new
palabra clave, el compilador crea un nuevo método no virtual solo para la clase derivada; el método de la clase base permanece intacto.
Si el tipo de la variable es Base
(es decir, solo contiene el método virtual), su implementación se resolverá a través del vtable. Si el tipo de la variable es New
, se invocará el método o propiedad no virtual.
{
Base b = new Base();
Console.WriteLine(b.Name); // prints "Base"
b = new New();
// type of `b` variable is `Base`, and `Base.Name` is virtual,
// so compiler resolves its implementation through the virtual table
Console.WriteLine(b.Name); // prints "Base"
New n = new New();
// type of `n` variable is `New`, and `New.Name` is not virtual,
// so compiler sees `n.Name` as a completely different property
Console.WriteLine(n.Name); // prints "New"
}
3. Resumen
Si una parte de su código acepta el tipo de base, siempre usará la tabla virtual durante el tiempo de ejecución. Para la mayoría de los escenarios OOP, esto significa que marcar un método como new
es muy similar a darle un nombre completamente diferente.
4. Tamaños de objeto después de instanciación
Tenga en cuenta que la instancia de cualquiera de estos tipos no crea una copia de la tabla virtual. Cada objeto .NET tiene un par de bytes de encabezado y un puntero a la tabla virtual de la tabla de su tipo ( class
).
Con respecto a la new
propiedad (la que no es virtual), básicamente se compila como un método estático con esta semántica de llamada, lo que significa que tampoco agrega nada al tamaño de la instancia en la memoria.
Ya respondió aquí
Anulación es la definición de múltiples implementaciones posibles de la misma firma de método, de modo que la implementación está determinada por el tipo de tiempo de ejecución del argumento zeroth (generalmente identificado por el nombre this en C #).
Ocultar es la definición de un método en un tipo derivado con una firma idéntica a la de uno de sus tipos básicos sin anulación.
La diferencia práctica entre anular y ocultar es la siguiente:
Ocultar es para todos los demás miembros (métodos estáticos, miembros de instancia, miembros estáticos). Se basa en la vinculación temprana. Más claramente, el método o miembro a ser llamado o utilizado se decide durante el tiempo de compilación.
• Si se invalida un método, la implementación para llamar se basa en el tipo de tiempo de ejecución del argumento this. • Si un método simplemente está oculto, la implementación para llamar se basa en el tipo de tiempo de compilación del argumento this.
Aquí hay algunas muestras: Ejemplo # 1 . y Ejemplo # 2
class Base {
int a;
public void Addition() {
Console.WriteLine("Addition Base");
}
public virtual void Multiply()
{
Console.WriteLine("Multiply Base");
}
public void Divide() {
Console.WriteLine("Divide Base");
}
}
class Child : Base
{
new public void Addition()
{
Console.WriteLine("Addition Child");
}
public override void Multiply()
{
Console.WriteLine("Multiply Child");
}
new public void Divide()
{
Console.WriteLine("Divide Child");
}
}
class Program
{
static void Main(string[] args)
{
Child c = new Child();
c.Addition();
c.Multiply();
c.Divide();
Base b = new Child();
b.Addition();
b.Multiply();
b.Divide();
b = new Base();
b.Addition();
b.Multiply();
b.Divide();
}
}
Salida: -
Niño adicional
Multiplicar niño
Divide Child
Base de adición
Multiplicar niño
Divide Base
Base de adición
Multiplicar la base
Divide Base
En el momento de anular el compilador comprueba el objeto de la clase, pero en oculto, el compilador solo comprueba la referencia de la clase