Il y a une différence entre new
et virtual
/ override
.
Vous pouvez imaginer qu'une classe, une fois instanciée, n'est rien de plus qu'une table de pointeurs, pointant vers l'implémentation réelle de ses méthodes. L'image suivante devrait bien visualiser cela:
Maintenant, il existe différentes manières, une méthode peut être définie. Chacun se comporte différemment lorsqu'il est utilisé avec l'héritage. La méthode standard fonctionne toujours comme l'illustre l'image ci-dessus. Si vous souhaitez modifier ce comportement, vous pouvez associer différents mots-clés à votre méthode.
1. Classes abstraites
Le premier est abstract
. abstract
les méthodes ne pointent simplement nulle part:
Si votre classe contient des membres abstraits, elle doit également être marquée comme abstract
, sinon le compilateur ne compilera pas votre application. Vous ne pouvez pas créer d'instances de abstract
classes, mais vous pouvez en hériter et créer des instances de vos classes héritées et y accéder à l'aide de la définition de classe de base. Dans votre exemple, cela ressemblerait à:
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!");
}
}
S'il est appelé, le comportement de ShowInfo
varie en fonction de l'implémentation:
Person person = new Teacher();
person.ShowInfo(); // Shows 'I am a teacher!'
person = new Student();
person.ShowInfo(); // Shows 'I am a student!'
Les deux, Student
s et Teacher
s sont des Person
s, mais ils se comportent différemment quand on leur demande de demander des informations sur eux-mêmes. Cependant, la façon de leur demander de demander leurs informations est la même: en utilisant l' Person
interface de classe.
Alors que se passe-t-il dans les coulisses, lorsque vous héritez Person
? Lors de l'implémentation ShowInfo
, le pointeur ne pointe plus vers nulle part , il pointe désormais vers l'implémentation réelle! Lors de la création d'une Student
instance, il pointe vers Student
s ShowInfo
:
2. Méthodes virtuelles
La deuxième façon est d'utiliser des virtual
méthodes. Le comportement est le même, sauf que vous fournissez une implémentation par défaut facultative dans votre classe de base. Les classes avec des virtual
membres peuvent être instanciées, mais les classes héritées peuvent fournir différentes implémentations. Voici à quoi votre code devrait ressembler pour fonctionner:
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 principale différence est que le membre de base Person.ShowInfo
ne pointe plus vers nulle part . C'est également la raison pour laquelle vous pouvez créer des instances de Person
(et il n'est donc pas nécessaire de le marquer abstract
plus longtemps):
Vous devriez remarquer que cela ne semble pas différent de la première image pour le moment. C'est parce que la virtual
méthode pointe vers une implémentation «à la manière standard ». En utilisant virtual
, vous pouvez dire Persons
qu'ils peuvent (pas obligés ) fournir une implémentation différente pour ShowInfo
. Si vous fournissez une implémentation différente (en utilisant override
), comme je l'ai fait pour ce qui Teacher
précède, l'image aura la même apparence que pour abstract
. Imaginez, nous n'avons pas fourni d'implémentation personnalisée pour Student
s:
public class Student : Person
{
}
Le code serait appelé comme ceci:
Person person = new Teacher();
person.ShowInfo(); // Shows 'I am a teacher!'
person = new Student();
person.ShowInfo(); // Shows 'I am a person!'
Et l'image de Student
ressemblerait à ceci:
3. Le mot-clé magique `new` aka" Shadowing "
new
est plus un hack autour de cela. Vous pouvez fournir des méthodes dans des classes généralisées, qui ont les mêmes noms que des méthodes dans la classe / interface de base. Les deux pointent vers leur propre implémentation personnalisée:
L'implémentation ressemble à celle que vous avez fournie. Le comportement diffère selon la manière dont vous accédez à la méthode:
Teacher teacher = new Teacher();
Person person = (Person)teacher;
teacher.ShowInfo(); // Prints 'I am a teacher!'
person.ShowInfo(); // Prints 'I am a person!'
Ce comportement peut être souhaité, mais dans votre cas, il est trompeur.
J'espère que cela rend les choses plus claires à comprendre pour vous!