visual studio polimorfismo polimorfico herencia derivada composicion clase abstraccion c# casting

studio - polimorfismo c#



Cuando un objeto se lanza a una clase base, ¿cómo recuerda lo que realmente es? (5)

Esta es una pregunta para principiantes, pero estoy interesado en saber qué está pasando aquí. Mi pregunta es, ¿qué sucede detrás de escena cuando arrojas un objeto? ¿Mantiene algún tipo de metadata sobre lo que originalmente era? Esto es lo que quiero decir:

Supongamos que tengo un método llamado "ClockIn" que acepta un parámetro de tipo "Empleado":

public static void ClockIn(Employee employee) { var manager = employee as Manager; if (manager != null) { manager.OpenSafe(); } }

Entonces, suponga que Manager es una subclase del tipo Employee y que tiene el método "OpenSafe":

public class Manager : Employee { public void OpenSafe() { ... } }

El método "ClockIn", si encuentra que se ha pasado un Manager, llama al método OpenSafe. Como:

var bob = new Manager(); ClockIn(bob);

Aquí, pasé en una instancia de Type Manager a un método que acepta la clase base Employee. Necesito enviar la instancia dentro del método ClockIn al Administrador antes de poder llamar a OpenSafe.

La pregunta es, ¿hay algunos metadatos que recuerden que "bob" es un administrador, a pesar de que lo pasé como un empleado? ¿Cómo sabe el código que puede ser enviado a un Gerente? ¿Hay algo pasando en el montón?


El tipo real de objeto siempre se almacena como un enlace a su System.Type . En realidad, cada objeto .NET tiene un campo System.Type adicional que hace referencia a su tipo real.


Extendiendo las respuestas anteriores, es útil pensar que los aspectos públicos de una clase son como un panel eléctrico. Los puntos de conexión del mundo exterior fijos se conectan al funcionamiento interno de la clase. Si una clase hereda otra clase, los objetos de la nueva clase obtienen un panel etiquetado con su nuevo tipo de clase, además de tener un panel del tipo de clase base. Agregar una interfaz agrega otro panel.

Si una propiedad o método se declara invalidable, la parte posterior de la "conexión" del panel para ese método / propiedad tendrá un enchufe extraíble; de lo contrario no lo hará. Supongamos que una clase "Alpha" tiene un método "foo" y una "barra" de funciones no reemplazables. Una clase derivada "Bravo" anula "foo" y sombrea "barra". Los objetos de la clase "Bravo" tendrán tanto "Alpha.foo" como "Bravo.foo" conectados a la función "foo" de Bravo; Tendrán "Alpha.Bar" conectado a la función "Bar" de Alpha, y "Bravo.Bar" conectado a la función "Bar" de Bravo.

Si se utiliza un objeto "BravoInstance" de tipo "Bravo" en algún lugar donde se espera un "Bravo", una referencia a su "BravoInstance.Bar" hará que el sistema vea el panel "Bravo" del objeto y use su "Barra" conexión (conectada a Bravo.Bar). Si tal instancia se le da al código que espera un Alpha (perfectamente permitido debido a la herencia), un intento de acceder a ThatInstance.Bar se conectará a la conexión "Bar" del panel "Alpha" (que a su vez está conectada a Alpha.Bar) .

Hay momentos en que el sombreado es útil y apropiado, pero se debe tener mucho cuidado al sombrear un método o propiedad de un objeto que se puede pasar al código que espera el tipo de base.


La conversión no afecta al objeto; afecta la referencia al objeto.

Todo lo que está haciendo cuando baja un objeto es decirle al compilador que este objeto puede ser referenciado por una variable que deriva del tipo que hace referencia actualmente al objeto.

El punto clave es que la clase del objeto nunca cambia, solo está cambiando el tipo de la referencia al objeto.


Lo primero que debe recordar es que el casting no cambia el objeto original en absoluto. Solo cambia la vista del objeto a través de esa referencia en particular. Más de una referencia puede estar apuntando al mismo objeto, por lo que no es razonable cambiar el objeto en un molde.

Lo que podría hacer en su instancia es hacer que ClockIn() un método de la clase Employee . Entonces, cuando llamas

bob.ClockIn();

entonces bob sabrá qué tipo es realmente y llamará al método ClockIn() apropiado para su tipo. Esto se llama despacho de método dinámico y no está disponible para funciones static como en su ejemplo.

Por ejemplo:

public class Employee { public void ClockIn() { .... } } public class Manager: Employee { public void ClockIn() { // first, do what all Employees do when clocking in Employee.ClockIn(); // Next, do Manager specific actions OpenSafe(); } public void OpenSafe() { .... } }


Los moldes no cambian el tipo de tiempo de ejecución de un objeto.

Llamar al método GetType en un objeto devolverá un objeto Type que represente su tipo de tiempo de ejecución.