C # 8: méthode d'interface par défaut

Traduit de l'article de John Demetriou «C # 8: Default Interface Methods» 1 du 4 août 2018, avec du contenu ajouté

Avant C # 8

Aujourd'hui, nous allons parler de la méthode d'interface par défaut. Cela semble vraiment bizarre, n'est-ce pas? L'interface sert uniquement à définir le contrat. La classe d'implémentation de l'interface aura un ensemble de méthodes publiques, mais la classe d'implémentation a la liberté d'implémenter chaque méthode à sa manière. Jusqu'à présent, si nous devons fournir une implémentation pour une ou plusieurs de ces méthodes, nous utiliserons l'héritage.
Si nous espérons que cette classe n'implémentera pas toutes les méthodes, mais seulement un sous-ensemble d'entre elles, nous pouvons faire abstraction de ces méthodes et de la classe elle-même ( abstract).

Par exemple, nous ne pouvons pas écrire:

interface IExample
{
    
    
    void Ex1();                                      // 允许
    void Ex2() => Console.WriteLine("IExample.Ex2"); // 不允许(C# 8 以前)
}

Nous devons le remplacer par la classe abstraite suivante:

abstract class ExampleBase
{
    
    
    public abstract void Ex1();
    public void Ex2() => Console.WriteLine("ExampleBase.Ex2");
}

Heureusement, cela suffit pour répondre à la plupart de nos besoins.

Après C # 8

Alors, y a-t-il un changement, pourquoi devons-nous introduire cette nouvelle fonctionnalité? Qu'avons-nous manqué et n'avons-nous jamais remarqué ce que nous avons manqué?

Problème de diamant

En raison du problème Diamond 2 , C # (et de nombreux autres langages) ne prend pas en charge l'héritage multiple. Afin d'autoriser l'héritage multiple tout en évitant le problème du diamant, C # 8 a introduit des méthodes d'interface par défaut.

À partir de C # 8, en utilisant la méthode d'interface par défaut, vous pouvez avoir une définition d'interface et l'implémentation par défaut de certaines ou de toutes les méthodes de la définition.

interface IExample
{
    
    
    void Ex1();                                      // 允许
    void Ex2() => Console.WriteLine("IExample.Ex2"); // 允许
}

Par conséquent, vous pouvez maintenant implémenter une interface avec des méthodes implémentées et vous pouvez éviter la duplication de code dans les classes que vous souhaitez hériter d'une classe spécifique (qui contient également des méthodes courantes).

En utilisant la méthode d'interface par défaut, le problème du diamant n'a pas été résolu à 100%. Cela peut toujours se produire lorsqu'une classe hérite de deux interfaces héritées de la troisième interface et que toutes les interfaces implémentent la même méthode.
Dans ce cas, le compilateur C # choisira d'appeler la méthode appropriée en fonction du contexte actuel. Si une erreur spécifique ne peut pas être déduite, une erreur de compilation sera affichée.

Par exemple, supposons que nous ayons l'interface suivante:

interface IA
{
    
    
    void DoSomething();
}

interface IB : IA
{
    
    
    void DoSomething() => Console.WriteLine("I am Interface B");
}

interface IC : IA
{
    
    
    void DoSomething() => Console.WriteLine("I am Interface C");
}

Ensuite, je crée une classe Dqui implémente les deux interfaces ci-dessus , ce qui provoquera une erreur de compilation:

//编译器提示:“D”未实现接口成员“IA.DoSomething()”
public class D : IB, IC
{
    
     }

Cependant, s'il s'agit d'une classe Dde sa propre version de la réalisation de DoSomethingla méthode, le compilateur saura quelle méthode appelle:

public class D : IB, IC
{
    
    
    public void DoSomething() => Console.WriteLine("I am Class D");
}

Si le code de la méthode principale est le suivant:

static void Main()
{
    
    
    var x = new D();
    x.DoSomething();
    Console.ReadKey();
}

Exécutez le programme, la I am Class Dsortie de la

Autres bénéfices

À l'aide de l'implémentation d'interface par défaut de la méthode, le fournisseur d'API peut étendre l'interface existante sans casser aucune partie du code hérité.

Mode trait

Note du traducteur:
En programmation informatique, Trait est un concept utilisé dans la programmation orientée objet, qui représente un ensemble de méthodes pouvant être utilisées pour étendre les fonctionnalités d'une classe. 3

Le modèle de trait est essentiellement un ensemble de méthodes requises par plusieurs classes.
Auparavant, le modèle Trait en C # était implémenté à l'aide de classes abstraites. Mais comme l'héritage multiple n'est pas disponible, la mise en œuvre du modèle Trait devient très délicate, de sorte que la plupart des gens l'évitent ou se perdent dans une énorme chaîne d'héritage.

Cependant, en utilisant l'implémentation de la méthode par défaut dans l'interface, cela changera. Nous pouvons implémenter en utilisant la méthode d'interface par défaut dans l'interface, fournir un ensemble de méthodes qui doivent appartenir à la classe, puis laisser ces classes hériter de cette interface.
Bien sûr, n'importe quelle classe peut remplacer ces méthodes avec leur propre implémentation, mais au cas où elles ne le souhaiteraient pas, nous leur fournissons un ensemble d'implémentations par défaut.

Ce qui suit est le supplément du traducteur

Méthodes spécifiques dans l'interface

La forme la plus simple de la méthode d'interface par défaut consiste à déclarer une méthode spécifique dans l'interface , qui est une méthode avec une partie du corps.

interface IA
{
    
    
    void M() {
    
     Console.WriteLine("IA.M"); }
}

La classe qui implémente cette interface n'a pas besoin d'implémenter ses méthodes spécifiques.

class C : IA {
    
     } // OK

static void Main()
{
    
    
    IA i = new C();
    i.M(); // 输出 "IA.M"
}

La classe Cdans IA.Mla substitution finale est en IAparticulier une méthode déclarée M.
Veuillez noter qu'une classe ne peut implémenter qu'une interface et n'hérite pas des membres de l'interface :

C c = new C(); // 或者 var c = new C();
c.M();         // 错误: 类 'C' 不包含 'M' 的定义

Mais si la classe qui implémente cette interface implémente également des méthodes spécifiques, la signification est la même que l'interface générale:

class C : IA
{
    
    
    public void M() {
    
     Console.WriteLine("C.M"); }
}

static void Main()
{
    
    
    IA i = new C();
    i.M(); // 输出 "C.M"
}

Comment l'interface enfant appelle-t-elle la méthode de l'interface parent?

C'est une question posée par un ami dans le jardin du blog dans les commentaires. À première vue, cette question est assez intéressante: rencontrerez-vous une telle demande dans la réalité? Si vous y réfléchissez, vous pourriez l'utiliser. Voici un exemple simple à démontrer, dans l'interface IBpour appeler la IAméthode des membres de l' interface parent M, comme suit:

interface IA
{
    
    
    void M() {
    
     Console.WriteLine("IA.M"); }
}

interface IB : IA
{
    
    
    //void IA.M() { Console.WriteLine("IB.M"); }

    void IB_M() {
    
     M(); }
}

class C : IB {
    
     }

static void Main(string[] args)
{
    
    
    IB i = new C();
    i.IB_M();  // 输出 "IA.M";如果把 IB 中的注释行打开,这里会输出 "IB.M"
}

Auteur: John Demetriou
Traducteur: Technical Zemin
Editeur: Technical Verses
links: English text

Numéro public: Station de traduction technique


  1. https://www.devsanon.com/c/c-8-default-interface-methods/ C # 8: Méthodes d'interface par défaut ↩︎

  2. https://mp.weixin.qq.com/s/EZ_jIjT6hYFrhbJ9BZ7 Problème de diamant BMWmw

  3. https://en.wikipedia.org/wiki/Trait_(computer_programming) Trait ↩︎

Je suppose que tu aimes

Origine blog.csdn.net/weixin_47498376/article/details/109225942
conseillé
Classement