c# - sombra - ¿Qué es el sombreado?
sombra a elemento css (11)
En C #, ¿qué significa el término sombreado ? He leído este enlace pero no lo entendí del todo.
Aquí hay un artículo de MSDN sobre Shadowing. Los ejemplos de lenguaje están en Visual Basic (desafortunadamente no hay una página equivalente de C # en MSDN), pero trata generalmente con los conceptos y, con suerte, debería ayudarlo a comprender de todos modos.
Editar: Parece que hay un artículo de C # sobre el sombreado, excepto que se llama ocultar en C #. Además, esta página ofrece una buena visión general.
El remedo consiste en ocultar un método de clase base con una nueva definición en una clase hija.
La diferencia entre ocultar y anular tiene que ver con la forma en que se invocan los métodos.
De esta forma, cuando se anula un método virtual, la dirección de llamada para la tabla de llamadas a métodos de la clase base se reemplaza por la dirección de la rutina secundaria.
Por otro lado, cuando se oculta un método, se agrega una nueva dirección a la tabla de llamadas al método de la clase secundaria.
Cuando se realiza una llamada al método en cuestión:
- Se obtiene el tipo de clase de tabla de llamada de método, si invocamos con una referencia a la clase base, entonces se obtiene la tabla de método de clase base, si tenemos una referencia a la clase hija, entonces se obtiene la tabla de método de clase hija.
- El método se busca en la tabla, si se encuentra, la invocación se lleva a cabo, de lo contrario, se busca en la tabla de métodos de la clase base.
Si invocamos el método con una referencia a la clase hija, entonces el comportamiento es el mismo, si el método ha sido anulado, la dirección del método se encontrará en la clase base; si el método está oculto, la dirección del método se encontrará en el clase secundaria, y como ya se ha encontrado, no se buscará la tabla de clases base.
Si invocamos el método con una referencia a la clase base, el comportamiento cambia. Al anular, como la dirección del método sobrescribe la entrada de la clase base, llamaremos al método secundario, incluso cuando se mantiene una referencia a la clase base. Con el sombreado, la tabla de métodos de la clase base (que es la única visible al mantener una referencia a la clase base) contiene la dirección del método virtual y, por lo tanto, se llamará al método de la clase base.
En general, el sombreado es una mala idea, ya que introduce una diferencia en el comportamiento de una instancia según la referencia que tengamos.
El sombreado no es algo que me preocuparía comprender o implementar a menos que "encaje" muy bien con el problema. Lo he visto usar incorrectamente y causar extraños errores de lógica mucho más a menudo que ser usado correctamente. La gran causa, creo, es cuando el programador olvida poner anulaciones en una firma de método, entonces la advertencia del compilador sugerirá la nueva palabra clave. Siempre he sentido que debería recomendar el uso de la anulación.
El sombreado oculta un método en una clase base. Usando el ejemplo en la pregunta que vinculó:
class A
{
public int Foo(){ return 5;}
public virtual int Bar(){return 5;}
}
class B : A
{
public new int Foo() { return 1;}
public override int Bar() {return 1;}
}
La clase B
anula la Bar
métodos virtuales. Oculta (sombrea) el método no virtual Foo
. La anulación usa la palabra clave de anulación . El sombreado se hace con la nueva palabra clave.
En el código anterior, si no usó la palabra clave nueva al definir el método Foo
en la clase B
, obtendrá esta advertencia del compilador:
''test.B.Foo()'' hides inherited member ''test.A.Foo()''. Use the new keyword if hiding was intended.
Espero que esta breve explicación ayude.
Shadowing
- Reemplaza el elemento completo de la clase padre
class InventoryAndSales
{
public int InvoiceNumber { get; set; }
}
//if someone calls for this class then the InvoiceNumber type is now object
class NewInventoryAndSales : InventoryAndSales
{
public new object InvoiceNumber { get; set; }
}
Overriding
: solo reemplaza la implementación. No reemplaza el tipo de datos que no reemplaza, como por ejemplo, si tiene una variable, no la convierte en un método, de modo que si hay un método, usará ese método y solo cambiará la implementación.
class InventoryAndSales
{
public virtual int GetTotalSales(int a, int b)
{
return a + b;
}
}
class NewInventoryAndSales : InventoryAndSales
{
//it replaces the implementation in parent class
public override int GetTotalSales(int a, int b)
{
return a * b;
}
}
Expandiendo la respuesta correcta de Kent
Cuando desambiqué cuándo se llamará a ese método, me gusta pensar en sombrear vs. anular con el siguiente
- Sombreado: El método llamado depende del tipo de referencia en el punto en que se realiza la llamada
- Anulación: el método llamado depende del tipo de objeto en el punto donde se realiza la llamada.
Si quiere ocultar el método de la clase Base, use la anulación en la base [método virtual en la base]
si quiere ocultar el método de la clase Child, use new in base [método no virtual en la base] -> shadow
Base B=new Child()
B.VirtualMethod()
-> Método de clase Child Calls
B.NonVirtualMethod()
-> Método de la clase Base de llamadas
Supongamos que tengo una clase base que implementa un método virtual:
public class A
{
public virtual void M() { Console.WriteLine("In A.M()."); }
}
También tengo una clase derivada que también define un método M:
public class B : A
{
// could be either "new" or "override", "new" is default
public void M() { Console.WriteLine("In B.M()."); }
}
Ahora, supongamos que escribo un programa como este:
A alpha = new B(); // it''s really a B but I cast it to an A
alpha.M();
Tengo dos opciones diferentes de cómo quiero que se implemente. El comportamiento predeterminado es llamar a la versión A de M. (Esto es idéntico al comportamiento si aplica la palabra clave " new
" a BM()
.
Esto se denomina "sombreado" cuando tenemos un método con el mismo nombre pero un comportamiento diferente cuando se lo llama desde la clase base.
Alternativamente, podríamos haber especificado " override
" en BM()
. En este caso, alpha.M()
habría llamado la versión B de M.
Anulación : mismo nombre y exactamente los mismos parámetros, implementados de manera diferente en las subclases.
- Si se trata como DerivedClass o BaseClass, utilizó el método derivado.
Sombreado : el mismo nombre y exactamente los mismos parámetros, implementados de forma diferente en las subclases.
- Si se trata como DerivedClass, utilizó el método derivado.
- si se trata como BaseClass, usa el método base.
private static int x = 10;
static void Main(string[] args)
{ int x = 20;
if (Program.x == 10)
{
Console.WriteLine(Program.x);
}
Console.WriteLine(x);}
Salida:
10 20
- Anulación: redefinir un método existente en una clase base
- Sombreado: crear un método completamente nuevo con la misma firma que uno en una clase base