92 votes

Classes abstraites, interfaces et mixins

Quelqu'un pourrait-il m'expliquer les différences entre classes abstraites , interfaces y mixins ? J'ai déjà utilisé les deux dans mon code mais je ne connais pas les différences techniques.

100voto

Eva Points 1078

Classe abstraite

Une classe abstraite est une classe qui n'est pas conçue pour être instanciée. Les classes abstraites peuvent n'avoir aucune implémentation, une certaine implémentation ou toutes les implémentations. Les classes abstraites sont conçues pour permettre à leurs sous-classes de partager une implémentation commune (par défaut). Un exemple (pseudocodé) d'une classe abstraite serait quelque chose comme ceci

abstract class Shape {
    def abstract area();  // abstract (unimplemented method)
    def outline_width() = { return 1; }  // default implementation
}

Une sous-classe pourrait ressembler à

class Rectangle extends Shape {
    int height = width = 5;
    def override area() = { return height * width; }  // implements abstract method
    // no need to override outline_width(), but may do so if needed
}

Utilisation possible

def main() = {
    Shape[] shapes = { new Rectangle(), new Oval() };
    foreach (s in shapes) {
        print("area: " + s.area() + ", outline width: " + s.outline_width());
    }
}

Si une sous-classe ne surcharge pas les méthodes non implémentées, elle est également une classe abstraite.

Interface

En termes généraux d'informatique, une interface est la partie d'un programme exposée à un client. Les classes et les membres publics sont des exemples d'interfaces.

Java et C# ont une interface mot-clé. Il s'agit plus ou moins d'une classe abstraite sans implémentation. (Il y a des trucs à propos des constantes, des classes imbriquées, de l'implémentation explicite et des modificateurs d'accès que je ne vais pas aborder). Bien que la partie "pas d'implémentation" ne soit plus valable en Java, ils ont ajouté des méthodes par défaut. Le site interface Le mot-clé peut être considéré comme une réification du concept d'interface.

Revenons à l'exemple de la forme

interface Shape {
    def area();  // implicitly abstract so no need for abstract keyword
    def outline_width();  // cannot implement any methods
}

class Rectangle implements Shape {
    int height = width = 5;
    def override area() = { return height * width; }
    def override outline_width() = { return 1; }  // every method in interface must be implemented
}

def main() = {
    Shape[] shapes = { new Rectangle(), new Oval() };
    foreach (s in shapes) {
        print("area: " + s.area() + ", outline width: " + s.outline_width());
    }
}

Java et C# ne permettent pas l'héritage multiple de classes avec implémentation, mais ils permettent l'implémentation multiple d'interfaces. Java et C# utilisent les interfaces comme solution de rechange à l'héritage multiple des classes. Problème mortel du diamant de la mort que l'on trouve dans les langages qui permettent l'héritage multiple (qui n'est pas vraiment mortel, s'il est correctement géré).

Mixin

Un mixin (parfois appelé trait) permet l'héritage multiple de classes abstraites. Les mixins n'ont pas l'association effrayante que l'héritage multiple a (à cause de la folie du C++), donc les gens sont plus à l'aise pour les utiliser. Ils présentent exactement le même problème de diamant de la mort, mais les langages qui les prennent en charge ont des moyens plus élégants de l'atténuer que le C++, et ils sont donc perçus comme meilleurs.

Les mixins sont salués comme des interfaces avec réutilisation comportementale , plus flexible les interfaces, et plus puissant interfaces. Vous remarquerez que toutes ces interfaces ont le terme interface dans celles-ci, en faisant référence au mot-clé Java et C#. Les mixins ne sont pas des interfaces. Ce sont des héritages multiples. Avec un nom plus joli.

Cela ne veut pas dire que les mixins sont mauvais. L'héritage multiple n'est pas mauvais. La façon dont le C++ résout l'héritage multiple est ce sur quoi tout le monde se déchaîne.

Revenons au vieil exemple du Shape

mixin Shape {
    def abstract area();
    def outline_width() = { return 1; }
}

class Rectangle with Shape {
    int height = width = 5;
    def override area() = { return height * width; }
}

def main() = {
    Shape[] shapes = { new Rectangle(), new Oval() };
    foreach (s in shapes) {
        print("area: " + s.area() + ", outline width: " + s.outline_width());
    }
}

Vous remarquerez qu'il n'y a aucune différence entre cet exemple et celui de la classe abstraite.

Un détail supplémentaire est que C# supporte les mixins depuis la version 3.0. Vous pouvez le faire avec des méthodes d'extension sur les interfaces. Voici l'exemple de Shape avec du vrai( !) code C# style mixin

interface Shape
{
    int Area();
}

static class ShapeExtensions
{
    public static int OutlineWidth(this Shape s)
    {
        return 1;
    }
}

class Rectangle : Shape
{
    int height = 5;
    int width = 5;

    public int Area()
    {
        return height * width;
    }
}

class Program
{
    static void Main()
    {
        Shape[] shapes = new Shape[]{ new Rectangle(), new Oval() };
        foreach (var s in shapes)
        {
            Console.Write("area: " + s.Area() + ", outline width: " + s.OutlineWidth());
        }
    }
}

22voto

Paul Morie Points 6956

En général :

Un site interface est un contrat spécifiant des opérations, mais sans aucune implémentation. Certains langages (Java, C#) ont un support intégré pour les interfaces, et dans d'autres, "interface" décrit une convention comme une classe virtuelle pure en C++.

Un site classe abstraite est une classe qui spécifie au moins une opération sans implémentation. Les classes abstraites peuvent également fournir certaines parties de leur implémentation. Là encore, certains langages ont un support intégré pour marquer les classes comme étant abstraites, tandis que d'autres le font implicitement. Par exemple, en C++, une classe qui définit une méthode virtuelle pure est abstraite.

A mixin est une classe conçue pour faciliter la mise en œuvre de certaines fonctionnalités dans les sous-classes, mais qui n'est pas conçue pour être utilisée seule. Par exemple, disons que nous disposons d'une interface pour un objet qui traite les requêtes

interface RequestHandler {
  void handleRequest(Request request);
}

Il serait peut-être utile de mettre les demandes en mémoire tampon en les accumulant jusqu'à un nombre prédéterminé, puis de vider la mémoire tampon. Nous pouvons implémenter la fonctionnalité de mise en mémoire tampon avec un mixin sans spécifier le comportement du flush :

abstract class BufferedRequestHandlerMixin implements RequestHandler {
  List<Request> buffer = new List<Request>();

  void handleRequest(Request request) {
    buffer.add(request);

    if (buffer.size == BUFFER_FLUSH_SIZE) {
        flushBuffer(buffer);
        buffer.clear();
    }
  }

  abstract void flushBuffer(List<Request> buffer);
}

Ainsi, il nous est facile d'écrire un gestionnaire de requêtes qui écrit les requêtes sur le disque, appelle un service Web, etc. sans réécrire la fonctionnalité de mise en mémoire tampon à chaque fois. Ces gestionnaires de requêtes peuvent simplement étendre BufferedRequestHandlerMixin et mettre en œuvre flushBuffer .

Un autre bon exemple de mixin est l'une des nombreuses classes de support de Spring, à savoir. HibernateDaoSupport .

8voto

Ravindra babu Points 5571

Puisque beaucoup d'entre vous ont expliqué les définitions et l'utilisation, je voudrais souligner seulement les points importants.

Interface :

  1. Pour définir un contrat (de préférence apatride - je veux dire sans variables)
  2. Pour lier des classes non liées avec " has a " capacités.
  3. Pour déclarer des variables constantes publiques (état immuable)

Classe abstraite :

  1. Partager le code entre plusieurs classes étroitement liées. Il établit " is a " relation.

  2. Partager un état commun entre les classes liées (l'état peut être modifié dans les classes concrètes).

Je réduis la différence avec un petit exemple.

Animal peut être une classe abstraite. Cat et Dog en étendant cette classe abstraite, on établit " is a " relation.

Chat is a Animal

Chien is a Animal.

Chien can mettre en œuvre Bark interface. Ensuite, le chien has a capacité de Barking.

Chat can mettre en œuvre Hunt l'interface. Ensuite, Cat has a la possibilité de chasser.

Homme qui est not Animal peut mettre en œuvre Hunt l'interface. Ensuite, l'homme has a la possibilité de chasser.

L'homme et l'animal (chat/chien) ne sont pas liés. Mais l'interface Hunt peut fournir la même capacité à des entités non liées.

Mixin :

  1. Si vous voulez un mélange des deux abstract class et interface . Particulièrement utile lorsque vous voulez imposer un nouveau contrat à de nombreuses classes sans rapport entre elles, où certaines d'entre elles doivent redéfinir un nouveau comportement et d'autres doivent s'en tenir à une mise en œuvre commune. Ajouter une implémentation commune dans le Mixin et permettre aux autres classes de redéfinir les méthodes du contrat si nécessaire.

Si je veux déclarer une classe abstraite, je suivrai l'une de ces deux approches.

  1. Déplacer toutes les méthodes abstraites vers interface et ma classe abstraite implémente cette interface.

    interface IHunt{
        public void doHunting();
    }
    abstract class Animal implements IHunt{
    
    }
    class Cat extends Animal{
        public void doHunting(){}
    }

Question connexe SE :

Quelle est la différence entre une interface et une classe abstraite ?

6voto

La référence à Java et l'exemple donné d'une classe abstraite pour fournir un mixin sont trompeurs. Tout d'abord, Java ne prend pas en charge les "mixins" par défaut. Dans les termes Java, classe abstraite et mixins deviennent confus.

Un mixin est un type qu'une classe peut implémenter en plus de son "type primaire" pour indiquer qu'elle fournit un comportement optionnel. Pour parler en termes de Java, un exemple serait votre objet de valeur commerciale implémentant Serializable.

Josh Bloch dit - "Les classes abstraites ne peuvent pas être utilisées pour définir des mixins - puisqu'une classe ne peut pas avoir plus d'un parent" ( Rappelez-vous que Java ne permet qu'un seul candidat "extends").

Recherchez des langages comme Scala et Ruby pour une mise en œuvre appropriée de la notion de "mixin".

4voto

Sumit Sengar Points 1

La signification de "Mixin" est parfaitement définie par Joshua Bloch dans son livre "Effective Java". Un extrait de ce même livre :

" mixin est un type qu'une classe peut implémenter en plus de son "type primaire" pour déclarer qu'elle fournit un comportement optionnel. Par exemple, Comparable est une interface mixine qui permet à une classe de déclarer que ses instances sont ordonnées par rapport à d'autres classes mutuellement comparables. mutuellement comparables. Une telle interface est appelée mixine parce qu'elle permet de "mélanger" la fonctionnalité optionnelle. fonctionnalité optionnelle d'être "mélangée" à la fonctionnalité primaire du type. "

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X