Héritage multiple et classes mixin

13.5 Héritage multiple et classes mixin

Objectifs d'apprentissage

À la fin de cette section, vous devriez être en mesure de :

  • Construire une classe qui hérite de plusieurs superclasses.
  • Identifier le problème du diamant au sein de l'héritage multiple.
  • Construire une classe mixin pour ajouter des fonctionnalités à une sous-classe.

Notions de base sur l'héritage multiple

L'héritage multiple (multiple inheritance) est un type d'héritage dans lequel une classe hérite de plusieurs classes. Une classe qui hérite de plusieurs classes énumère toutes ses superclasses dans la liste d'héritage de sa définition de classe. Ex. : class SubClass(SuperClass_1, SuperClass_2).

Faites le point

Organisation de l'héritage multiple

Concepts en pratique

Mise en œuvre de l'héritage multiple

Considérez le programme suivant :

    class A:
      def __init__(self, a_attr=2):
        self.a_attr = a_attr

    class B:
      def __init__(self, b_attr=4):
        self.b_attr = b_attr

    class C(A, B):
      def __init__(self, a_attr=5, b_attr=10, c_attr=20):
        A.__init__(self, a_attr)
        B.__init__(self, b_attr)
        self.c_attr = c_attr

    b_inst = B(2)
    c_inst = C(1, 2)
1.
Quelle est la valeur de c_inst.a_attr ?
  1. 1
  2. 5
  3. Error
2.
Quelle est la valeur de c_inst.c_attr ?
  1. 2
  2. 20
  3. Error
3.
Quelle est la valeur de b_inst.a_attr ?
  1. 2
  2. 4
  3. Error

Le problème du diamant et les classes mixin

L'héritage multiple doit être mis en œuvre avec précaution. Le problème du diamant (diamond problem) survient lorsqu'une classe hérite de plusieurs classes qui partagent une superclasse commune. Ex. : Dessert et BakedGood héritent toutes deux de Food, et ApplePie hérite de Dessert et de BakedGood.

Un schéma conceptuel illustrant une hiérarchie de classification. « ApplePie » est représenté comme un sous-type de « Dessert » et de « BakedGood », qui sont eux-mêmes tous deux des sous-types de « Food ».
Figure 13.2 Le problème du diamant. Si
Dessert
et
BakedGood
redéfinissent toutes deux une méthode de
Food
, la méthode redéfinie de
Food
dont hérite
ApplePie
est ambiguë. Par conséquent, l'héritage en forme de diamant doit être évité.

Les classes mixin favorisent la modularité et peuvent éliminer le problème du diamant. Une classe mixin :

  • N'a pas de superclasse
  • Possède des attributs et des méthodes destinés à être ajoutés à une sous-classe
  • N'est pas instanciée (Ex. : étant donné une classe MyMixin, my_inst = MyMixin() ne devrait jamais être utilisé.)

Les classes mixin (mixin classes) sont utilisées dans l'héritage multiple pour ajouter des fonctionnalités à une sous-classe sans introduire de complications liées à l'héritage.

Concepts en pratique

Créer une classe mixin

Le code suivant n'est pas correct, car les plantes ne sont pas toutes carnivores. Suivez les modifications apportées par le développeur pour améliorer le programme. Remarque : Rose, Pitcher et VenusFlyTrap représentent des plantes qui réalisent toutes la photosynthèse. Pitcher et VenusFlyTrap représentent des plantes qui sont également carnivores et peuvent se nourrir.

Une instruction pass est utilisée en Python pour indiquer que du code sera écrit ultérieurement, et permet d'éviter certaines erreurs qui surviendraient si aucun code n'était écrit ou si un commentaire était utilisé à la place.

    class Plant:
      def photosynth(self):
        print("Photosynthesizing")

      def eat(self):
        print("Eating")

    class Rose(Plant):
      pass

    class Pitcher(Plant):
      pass
    
    class VenusFlyTrap(Plant):
      pass
4.
Quelle modification est appropriée ?
  1. Déplacer eat() dans une autre classe.
  2. Supprimer Plant en tant que superclasse.
5.
Le développeur modifie le code comme suit. Comment le programme peut-il être amélioré ?
class Plant:
  def photosynth(self):
    print("Photosynthesizing")

class Rose(Plant):
  pass

class Pitcher(Plant):
  def eat(self):
    print("Eating")

class VenusFlyTrap(Plant)
  def eat(self):
    print("Eating")
  1. Déplacer photosynth() dans Rose.
  2. Éliminer la redondance de eat().
6.
Le développeur modifie le code pour créer une classe mixin contenant eat(). Quel nom de classe, remplaçant X, est le plus approprié pour le mixin ?
class Plant:
  def photosynth(self):
    print("Photosynthesizing")

class X:
  def eat(self):
    print("Eating")

class Rose(Plant):
  pass

class Pitcher(Plant, X):
  pass

class VenusFlyTrap(Plant, X)
  pass
  1. CarnivClass
  2. CarnivMixin

À vous d'essayer

Résoudre le problème du diamant avec une classe mixin

Le programme ci-dessous illustre l'héritage multiple et présente le problème du diamant. Modifiez le programme pour utiliser une classe mixin, OnlineMixin. OnlineMixin :

  • Remplace OnlineShop.
  • Est une superclasse de FoodFast.
  • Possède une méthode, process_online(), qui affiche "Connecting to server" et qui est appelée par la méthode process_order() de FoodFast'.

La sortie doit correspondre à :

    Processing meal order
    Connecting to server
    Enjoy your FoodFast order