Hay una diferencia entre new
y virtual
/override
.
Puede imaginar que una clase, cuando se instancia, no es más que una tabla de punteros, que apunta a la implementación real de sus métodos. La siguiente imagen debería visualizar esto bastante bien:
Ahora hay diferentes formas, se puede definir un método. Cada uno se comporta de manera diferente cuando se usa con herencia. La forma estándar siempre funciona como lo ilustra la imagen de arriba. Si desea cambiar este comportamiento, puede adjuntar diferentes palabras clave a su método.
1. Clases abstractas
La primera de ellas es abstract
. abstract
los métodos simplemente apuntan a ninguna parte:
Si su clase contiene miembros abstractos, también debe marcarse como abstract
, de lo contrario, el compilador no compilará su aplicación. No puede crear instancias de abstract
clases, pero puede heredar de ellas y crear instancias de sus clases heredadas y acceder a ellas utilizando la definición de clase base. En su ejemplo, esto se vería así:
public abstract class Person
{
public abstract void ShowInfo();
}
public class Teacher : Person
{
public override void ShowInfo()
{
Console.WriteLine("I am a teacher!");
}
}
public class Student : Person
{
public override void ShowInfo()
{
Console.WriteLine("I am a student!");
}
}
Si se llama, el comportamiento de ShowInfo
varía, en función de la implementación:
Person person = new Teacher();
person.ShowInfo(); // Shows 'I am a teacher!'
person = new Student();
person.ShowInfo(); // Shows 'I am a student!'
Ambos, Student
s y Teacher
s son Person
s, pero se comportan de manera diferente cuando se les pide que soliciten información sobre ellos mismos. Sin embargo, la forma de pedirles que soliciten su información es la misma: usar la Person
interfaz de clase.
Entonces, ¿qué sucede detrás de escena, cuando heredas de Person
? Al implementar ShowInfo
, el puntero ya no apunta a ninguna parte , ¡ahora apunta a la implementación real! Al crear una Student
instancia, apunta a Student
s ShowInfo
:
2. Métodos virtuales
La segunda forma es usar virtual
métodos. El comportamiento es el mismo, excepto que proporciona una implementación predeterminada opcional en su clase base. Las clases con virtual
miembros pueden instanciarse, sin embargo, las clases heredadas pueden proporcionar implementaciones diferentes. Así es como debería verse realmente su código para funcionar:
public class Person
{
public virtual void ShowInfo()
{
Console.WriteLine("I am a person!");
}
}
public class Teacher : Person
{
public override void ShowInfo()
{
Console.WriteLine("I am a teacher!");
}
}
La diferencia clave es que el miembro base Person.ShowInfo
ya no apunta a ninguna parte . Esta es también la razón por la que puede crear instancias de Person
(y, por lo tanto, no es necesario que se marque abstract
más):
Debes notar que esto no se ve diferente de la primera imagen por ahora. Esto se debe a que el virtual
método apunta a una implementación "de la manera estándar ". Usando virtual
, puede decir Persons
, que pueden (no deben ) proporcionar una implementación diferente para ShowInfo
. Si proporciona una implementación diferente (usando override
), como lo hice para lo Teacher
anterior, la imagen se vería igual que para abstract
. Imagínese, no proporcionamos una implementación personalizada para Student
s:
public class Student : Person
{
}
El código se llamaría así:
Person person = new Teacher();
person.ShowInfo(); // Shows 'I am a teacher!'
person = new Student();
person.ShowInfo(); // Shows 'I am a person!'
Y la imagen para Student
se vería así:
3. La palabra clave mágica `new` también conocida como" Sombrear "
new
Es más un truco alrededor de esto. Puede proporcionar métodos en clases generalizadas, que tengan los mismos nombres que los métodos en la clase / interfaz base. Ambos apuntan a su propia implementación personalizada:
La implementación se parece a la que usted proporcionó. El comportamiento difiere según la forma en que accede al método:
Teacher teacher = new Teacher();
Person person = (Person)teacher;
teacher.ShowInfo(); // Prints 'I am a teacher!'
person.ShowInfo(); // Prints 'I am a person!'
Este comportamiento puede ser deseado, pero en su caso es engañoso.
¡Espero que esto te aclare las cosas!