You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.
 
 
 
 
 
 

207 lines
4.1 KiB

  1. Chapitre 16 - Héritage
  2. ======================
  3. Rappel - composition
  4. ---------------------
  5. Dans un chapitre précédent on a parlé de *composition* qui décrit une classe à l'intérieur
  6. d'une autre classe.
  7. Pour rappel::
  8. class Chat:
  9. def __init__(self, nom):
  10. self.nom = nom
  11. def ronronne(self):
  12. print(self.nom, 'fait: "prrrrr"')
  13. def caresse(self):
  14. self.ronronne()
  15. class Enfant:
  16. def __init__(self, prénom, chat):
  17. self.chat = chat
  18. def console(self):
  19. self.chat.caresse()
  20. Vocabulaire
  21. -----------
  22. Ici on va parler d'héritage, qui décrit une autre relation entre classes, appelée parfois un peu abusivement "partage de code".
  23. Pour indiquer qu'une classe ``B`` hérite d'une classe ``A``, on écrit ``A`` dans des parenthèses au moment de
  24. déclarer la classe ``B``::
  25. class A:
  26. ...
  27. class B(A):
  28. ...
  29. Les trois formulations suivantes sont souvent employées:
  30. * A est la classe *parente* de B.
  31. * B *hérite* de A.
  32. * B est une classe *fille* de A.
  33. Utilisation
  34. -----------
  35. Si une méthode n'est pas trouvée dans la classe courante, Python ira la
  36. chercher dans la classe parente::
  37. class A:
  38. def méthode_dans_a(self):
  39. print("dans A")
  40. class B(A):
  41. def méthode_dans_b(self):
  42. print("dans B")
  43. b = B()
  44. b.méthode_dans_b()
  45. # Affiche: 'dans B', comme d'habitude
  46. b.méthode_dans_a()
  47. # Affiche: 'dans A'
  48. Ordre de résolution
  49. --------------------
  50. S'il y a plusieurs classes parentes, Python les remonte toutes une à une.
  51. On dit aussi qu'il y a une *hiérarchie* de classes::
  52. class A:
  53. def méthode_dans_a(self):
  54. print("dans A")
  55. class B(A):
  56. def méthode_dans_b(self):
  57. print("dans B")
  58. class C(B):
  59. def méthode_dans_c(self):
  60. print("dans C")
  61. c = C()
  62. c.méthode_dans_a()
  63. # affiche: 'dans A'
  64. Avec \_\_init\_\_
  65. --------------------
  66. La résolution fonctionne pour toutes les méthodes, y compris ``__init__``::
  67. class A:
  68. def __init__(self):
  69. print("initialisation de A")
  70. class B(A):
  71. ...
  72. b = B()
  73. # affiche: "initialisation de A"
  74. Attributs
  75. ----------
  76. Même mécanisme pour les attributs::
  77. class A:
  78. def __init__(self):
  79. self.attribut_de_a = 42
  80. class B(A):
  81. ...
  82. b = B()
  83. print(b.attribut_de_a)
  84. # affiche: 42
  85. Surcharge
  86. ----------
  87. On peut aussi *surcharger* la méthode de la classe parente dans la classe fille::
  88. class A:
  89. def une_méthode(self):
  90. print("je viens de la classe A")
  91. class B(A):
  92. def une_méthode(self):
  93. print("je viens de la classe B")
  94. b = B()
  95. b.une_méthode()
  96. # affiche: "je viens de la classe B'
  97. super()
  98. -------
  99. On peut utiliser ``super()`` pour chercher *explicitement* une méthode dans la classe parente::
  100. class A:
  101. def une_méthode(self):
  102. print("je viens de la classe A")
  103. class B(A):
  104. def une_méthode(self):
  105. super().une_méthode()
  106. print("je viens de la classe B")
  107. b = B()
  108. b.une_méthode()
  109. # affiche:
  110. # je viens de la classe A
  111. # je viens de la classe B
  112. super() et \_\_init\_\_
  113. ------------------------
  114. Erreur très courante::
  115. class A:
  116. def __init__(self):
  117. self.attribut_de_a = "bonjour"
  118. class B(A):
  119. def __init__(self):
  120. self.attribut_de_b = 42
  121. b = B()
  122. print(b.attribut_de_b)
  123. # affiche: 42
  124. print(b.attribut_de_a)
  125. # erreur: AttributeError
  126. On a surchargé ``A.__init__()``, du coup l'initialisation de A n'a jamais
  127. été faite.
  128. La plupart du temps, si ``A`` et ``B`` ont de constructeurs, on appellera
  129. ``super().__init__()`` dans le constructeur de la classe fille::
  130. class A:
  131. def __init__(self):
  132. self.attribut_de_a = "bonjour"
  133. class B(A):
  134. def __init__(self):
  135. super().__init__()
  136. self.attribut_de_b = 42
  137. b = B()
  138. print(b.attribut_de_b)
  139. # affiche: 42
  140. print(b.attribut_de_a)
  141. # affiche: "bonjour"