Le quartierC# C#Pièce 5/7Intermédiaire

Héritage et interfaces

Réutiliser du code avec l'héritage, redéfinir un comportement avec virtual et override, et décrire un contrat commun avec une interface.

Ce que tu vas apprendre

  • Créer une classe qui hérite d'une autre et redéfinir une méthode.
  • Faire appel au comportement de la classe de base avec base.
  • Décrire un contrat avec une interface et l'implémenter dans plusieurs classes.

L'idée de l'héritage

Sur ton site de recettes, un dessert et un plat ont des points communs : un nom, un temps de préparation. Plutôt que de tout écrire deux fois, une classe peut hériter d'une autre. Elle reçoit alors ses membres et peut en ajouter.

La classe d'origine s'appelle la classe de base. La classe qui hérite s'appelle la classe dérivée.

public class Recette
{
    public string Nom { get; }

    public Recette(string nom)
    {
        Nom = nom;
    }

    public virtual string Decrire() => $"Recette : {Nom}";
}

public class Dessert : Recette
{
    public Dessert(string nom) : base(nom) { }
}

Dessert : Recette se lit « Dessert hérite de Recette ». Un Dessert possède la propriété Nom et la méthode Decrire sans les réécrire.

Le constructeur de Dessert appelle : base(nom) pour passer le nom au constructeur de la classe de base.

Redéfinir avec virtual et override

Un dessert veut se décrire autrement. La classe de base marque la méthode virtual (elle peut être redéfinie), et la classe dérivée utilise override :

public class Dessert : Recette
{
    public int Sucre { get; }

    public Dessert(string nom, int sucre) : base(nom)
    {
        Sucre = sucre;
    }

    public override string Decrire() => $"Dessert : {Nom}, {Sucre} g de sucre";
}

Le résultat dépend du type réel de l'objet :

Recette r = new Recette("Soupe");
Recette d = new Dessert("Tarte", 80);

Console.WriteLine(r.Decrire());   // Recette : Soupe
Console.WriteLine(d.Decrire());   // Dessert : Tarte, 80 g de sucre

La variable d a le type Recette, mais l'objet est un Dessert. C'est la version du Dessert qui s'exécute. On appelle cela le polymorphisme : un même appel, des comportements différents selon l'objet.

Réutiliser le parent avec base

Dans une méthode redéfinie, base.Methode() appelle la version de la classe de base :

public override string Decrire() => base.Decrire() + $" (dessert, {Sucre} g de sucre)";

Tu complètes ainsi le comportement au lieu de le remplacer.

Une classe ne peut hériter que d'une seule classe de base. Pour partager un comportement entre des classes sans lien de parenté, on utilise les interfaces, vues plus bas.

Classe abstraite

Parfois, la classe de base n'a pas de sens seule : une « recette » générique n'existe pas dans la cuisine. Marque-la abstract pour interdire de la créer directement :

public abstract class Recette
{
    public abstract int Minutes();
}

public class Crepes : Recette
{
    public override int Minutes() => 30;
}

Une méthode abstract n'a pas de corps. Chaque classe dérivée doit l'écrire avec override. Le mot-clé sealed fait l'inverse : il interdit à une classe d'être héritée.

Les interfaces

Une interface est un contrat : elle liste des membres qu'une classe doit fournir, sans écrire leur code. Par convention, son nom commence par un I.

public interface IPrix
{
    double CalculerPrix();
}

public class Crepes : IPrix
{
    public double CalculerPrix() => 3.5;
}

public class Menu : IPrix
{
    public double CalculerPrix() => 12.0;
}

Crepes : IPrix signifie que Crepes promet de fournir CalculerPrix. Si elle l'oublie, le compilateur refuse le programme.

Une classe peut implémenter plusieurs interfaces, en les séparant par des virgules. Ces deux classes n'ont aucun lien d'héritage, mais on peut les traiter ensemble :

var elements = new List<IPrix> { new Crepes(), new Menu() };

foreach (IPrix element in elements)
{
    Console.WriteLine(element.CalculerPrix());
}

Héritage ou interface

CritèreHéritageInterface
Code partagéOui, la classe de base le contientNon, seulement la liste des membres
Nombre autoriséUne seule classe de baseAutant que nécessaire
Relation« est un » (un Dessert est une Recette)« sait faire » (peut donner un prix)
Quand tu hésites, choisis l'interface. L'héritage lie deux classes de façon durable, ce qui rend les changements plus difficiles plus tard.

À retenir

  • class B : A fait hériter B de A ; : base(...) appelle le constructeur de la classe de base.
  • virtual autorise la redéfinition, override redéfinit, base. appelle la version du parent.
  • Une classe abstract ne peut pas être créée seule ; sealed interdit l'héritage.
  • Une interface est un contrat sans code (IPrix) qu'une classe implémente, et une classe peut en implémenter plusieurs.
  • Hérite pour partager du code entre classes proches, utilise une interface pour un comportement commun à des classes sans lien.

Pour aller plus loin

Sources officielles

Ensuite

Projet
Lignes de code
Niveau
Le quartier
Appartement
C#
Pièce
5/7
Plan n°
csharp/05.heritage-et-interfaces
Lignes de code · fiches rédigées à partir des documentations officielles, sources citées en bas de chaque page.