10 Surcharge
Surchage de l'affichage
Nous avons depuis le début de notre aventure utilisé la méthode Console.WriteLine
pour afficher des informations dans la console. Toutefois il s'agissait d'afficher directement des chaines de caractères ou des types scalaires. Que se passe t'il si nous passons un type non-scalaire à cette méthode ?
Exemple n°1
Au sein du Main
de votre classe Program de votre solution MesozoicSolution ajouter le code suivant:
Dinosaur dinosaur = new Stegosaurus("Louis", 12);
Console.WriteLine(dinosaur);
- Que se passe t'il si l'on exécute notre programme ?
- Comprenez-vous ce qui est affiché ?
La classe Object
Comme nous l'avons vu en cours, tout nos classes héritent automatiquement de la classe Object
.
Ainsi ce schéma UML:
est équivalent à celui-ci:
Par convention on ne fait pas figurer sur un diagramme de classe l'héritage par défaut de la classe object étant donné que celui-ci est implicite.
La méthode ToString
La classe object fournit une méthode ToString
qui retourne une chaîne qui représente l'objet actuel.
Ainsi ce code:
Dinosaur dinosaur = new Stegosaurus("Louis", 12);
Console.WriteLine(dinosaur);
est équivalent à celui-ci:
Dinosaur dinosaur = new Stegosaurus("Louis", 12);
Console.WriteLine(dinosaur.ToString());
ou encore à celui-ci:
Dinosaur dinosaur = new Stegosaurus("Louis", 12);
string dinosaur_repr = dinosaur.ToString();
Console.WriteLine(dinosaur_repr);
Cette méthode est bien évidemment surchargeable pour l'adapter à nos besoins:
public class Stegosaurus
{
public override string ToString()
{
// We only call base ToString from Object class Here
return base.ToString();
}
}
A vous de jouer
Nous allons implémenter une surchage de la méthode ToString au sein de la classe (abstraite) Dinosaur de sorte à obtenir ceci:
Dinosaur dinosaur = new Stegosaurus("Louis", 12);
Console.WriteLine(dinosaur); // Mesozoic.Stegosaurus = {name: Louis, age: 12}
- Créez les T.Us correspondant à notre besoin,
- Implémentez la méthode et vérifiez son fonctionnement.
Surcharge d'opérateur
Exemple n°2
Au sein du Main
de votre classe Program de votre solution MesozoicSolution ajouter le code suivant:
Dinosaur louis = new Stegosaurus("Louis", 12);
Dinosaur louis2 = new Stegosaurus("Louis", 12);
//Console.WriteLine(dinosaur);
Console.WriteLine(louis == louis2);
louis2 = louis;
Console.WriteLine(louis == louis);
- Que se passe t'il si l'on exécute notre programme ?
- Comprenez-vous pourquoi ?
La méthode Equals
La classe object fournit une méthode Equals
qui détermine si deux instances d'objets sont égales.
Ainsi ce code:
Dinosaur dinosaur = new Stegosaurus("Louis", 12);
Dinosaur dinosaur2 = new Stegosaurus("Louis", 12);
Console.WriteLine(dinosaur == dinosaur2);
est équivalent à celui-ci:
Dinosaur dinosaur = new Stegosaurus("Louis", 12);
Dinosaur dinosaur2 = new Stegosaurus("Louis", 12);
Console.WriteLine(dinosaur.Equals(dinosaur2));
HashCode
La méthode GetHashCode
fait office de fonction de hachage par défaut. C'est à dire qu'elle fournit pour un objet un code numérique unique créer à partir de ses attributs.
Voici un exemple de création d'un Hash pour une classe, le hash est une agrégation des hash des différents attribut de l'objet.
public class Dinosaur
{
public override int GetHashCode()
{
int hash = 13;
hash ^= this.name.GetHashCode();
hash ^= this.age.GetHashCode();
hash ^= this.Specie.GetHashCode();
return hash;
}
}
Cette méthode doit être implémenter pour permettre la comparaison d'objet, ainsi deux objets ayant les mêmes valeurs d'attributs retourneront le même hash.
Dinosaur louis = new Stegosaurus("Louis", 12);
Dinosaur louis2 = new Stegosaurus("Louis", 12);
Dinosaur nessie = new Diplodocus("Nessie", 11);
Console.WriteLine(louis.GetHashCode()); // 2034845202
Console.WriteLine(louis2.GetHashCode()); //2034845202
Console.WriteLine(nessie.GetHashCode()); //-275418933
On peut donc comparer la valeur des hash, toutefois il est possible de faire mieux avec la surcharge d'opérateur.
Surcharge d'opérateur(s)
La surchage d'opérateur en c# permet de préciser un comportement sur la comparaison entre deux instances. Ainsi il est possible d'implémenter un comportement spécifique pour l'opérateur d'égalité (==) entre deux instances d'une même classe. Il faudra également implémenter l'inverse de l'opérateur d'égalité .. la différence (!=).
L'opérateur d'égalité compare chaque attribut des objets pour valider leurs égalités. La différence fait l'inverse.
public class Dinosaur
{
public static bool operator ==(Dinosaur dino1, Dinosaur dino2)
{
return dino1.name == dino2.name && dino1.Specie == dino2.Specie && dino1.age == dino2.age;
}
public static bool operator !=(Dinosaur dino1, Dinosaur dino2)
{
return !(dino1 == dino2);
}
}
Implémentation de la méthode Equals
Enfin il est possible d'implémenter la méthode Equals en ce basant sur l'opérateur d'égalité. Remarquez l'introduction du mot clé is
qui valide le type d'un objet.
public class Dinosaur {
public override bool Equals(object obj)
{
return obj is Dinosaur && this == (Dinosaur)obj;
}
}
A vous de jouer
Nous allons implémenter une surchage de la méthode Equals et de l'opérateur d'égalité au sein de la classe (abstraite) Dinosaur de sorte à obtenir ceci:
Dinosaur dinosaur = new Stegosaurus("Louis", 12);
Stegosaurus dinosaur2 = new Stegosaurus("Louis", 12);
Dinosaur dinosaur3 = new Diplodocus("Louis", 12);
Console.WriteLine(dinosaur == dinosaur2); // True
Console.WriteLine(dinosaur == dinosaur3); // False
- Créez les T.Us correspondant à notre besoin,
- Implémentez les méthode(s) et vérifiez leurs fonctionnements.