interface default methods

Les méthodes par défaut dans les interfaces de C# 8

Une interface décrit un comportement qui sera implémenté par une classe. Traditionnellement, une interface ne contient que la signature des méthodes, jamais leur implémentation. Mais à partir de C# 8, une interface peut contenir des méthodes avec un corps par défaut. Autrement dit, une interface peut désormais contenir du comportement. Voyons pourquoi cette fonctionnalité a été introduite, et comment elle fonctionne.

Le problème

Le principal intérêt des méthodes par défaut est de permettre de faire évoluer une interface sans casser le code existant.

Prenons un exemple simple.

Je crée une interface ICar

public interface ICar
{
    void Drive();
}

Puis une classe Audi qui l’implémente

public class Audi : ICar
{
    public void Drive()
    {
        Console.WriteLine("Driving Audi...");
    }
}

Tout fonctionne correctement

Imaginons que je modifie l’interface ICar:

public interface ICar
{
    void Drive();
    void Charge();
}

Le compilateur exigera que toutes les classes qui implémentent ICar implémentent également Charge(). Sinon, la compilation échoue. C’est précisément ce problème que les méthodes par défaut viennent résoudre.

La solution – les méthodes par défaut

A partir de C# 8, on peut écrire:

public interface ICar
{
    void Drive();

    void Charge()
    {
        Console.WriteLine("Charging...");
    }
}

La classe Audi n’a rien à modifier. Elle compile toujours. On peut donc faire évoluer l’interface sans casser les implémentations existantes. Avant C# 8, si on voulait ce comportement, il fallait utiliser une classe abstraite.

Attention ! La méthode par défaut reste attachée à l’interface. Elle ne devient pas automatiquement un membre de la classe.

Ce code ne compile pas :

Audi audi = new Audi();
audi.Charge(); // Erreur

Pourquoi ? Parce que Charge() n’est pas une méthode déclarée dans Audi.

Il faut passer par une référence d’interface :

ICar car = new Audi();
car.Charge(); // OK

Mais rien n’empêche la classe de fournir sa propre implémentation:

public class Audi : ICar
{
    public void Drive()
    {
        Console.WriteLine("Driving Audi...");
    }

    public void Charge()
    {
        Console.WriteLine("Charging Audi...");
    }
}

Dans l’exécution ci-dessous, c’est l’implémentation de la classe qui sera exécutée:

Audi audi = new Audi();
audi.Charge(); // affiche "Charging Audi..."

Conclusion

Les méthodes par défaut dans les interfaces ne sont pas là pour écrire moins de code. Elles ont été introduites pour permettre aux auteurs de bibliothèques d’ajouter des membres à leurs interfaces sans casser les implémentations existantes. Utilisées correctement, elles permettent de faire évoluer un contrat d’interface.

Leave a Reply

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.