No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
Este repositorio está archivado. Puede ver los archivos y clonarlo, pero no puede subir cambios o reportar incidencias ni pedir Pull Requests.

02-composition.rst 3.2 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. Composition
  2. ============
  3. Définition
  4. -----------
  5. Une classe à l'intérieur d'une autre classe.
  6. Dépendances entre fonctions
  7. -----------------------------
  8. Exemple ::
  9. def calcule_x():
  10. ...
  11. # du code ici
  12. def fait_un_truc_avec_x(x):
  13. ...
  14. # du code ici
  15. x = calcule_x()
  16. fait_un_truc_avec_x(x)
  17. On voit que la fonction ``fait_un_truc_avec_x()`` prend un argument ``x``, qui est retourné
  18. par la fonction ``calcule_x()``.
  19. ``fait_un_truc_avec_x()`` doit donc être appelée *après* ``calcule_x()``. On dit que ``fait_un_truc_avec_x()``
  20. *dépend* de ``calcule_x()``.
  21. Dépendances entre classes
  22. -------------------------
  23. Un bon moyen d'introduire une dépendance entre deux classes est d'utiliser les constructeurs.
  24. Revoyons la classe Chat::
  25. class Chat:
  26. def __init__(self, nom):
  27. self.nom = nome
  28. Comme le constructeur de la classe Chat prend un nom en argument, il est impossible de construire
  29. des chats sans nom::
  30. chat = Chat()
  31. # erreur: TypeError: __init__() missing 1 required positional argument: 'nom'
  32. De la même façon, si on veut que tous les enfants aient un chat (pourquoi pas, après tout), on peut
  33. avoir une classe Enfant, dont le constructeur prend une instance de chat en plus du prénom::
  34. class Enfant:
  35. def __init__(self, prénom, chat):
  36. self.prénom = prénom
  37. self.chat = chat
  38. alice = Enfant("Alice")
  39. # erreur: TypeError: __init__() missing 1 required positional argument: 'chat'
  40. boule_de_poils = Chat("Boule de Poils")
  41. alice = Enfant("Alice", boule_de_poils)
  42. # OK!
  43. Utilisation de la composition
  44. -----------------------------
  45. Maintenant qu'on vit dans un monde où tous les enfants ont chacun un chat, on peut
  46. par exemple consoler tous les enfants en leur demandant de caresser leur chat, chat
  47. qui va ronronner et faire plaisir à son propriétaire.
  48. voici comment on peut coder cela: d'abord, on rajoute les méthodes ``caresse()``
  49. et ``ronronne()`` dans la classe chat::
  50. class Chat:
  51. def __init__(self, nom):
  52. self.nom = nom
  53. def ronronne(self):
  54. print(self.nom, 'fait: "prrrrr"')
  55. def caresse(self):
  56. self.ronronne()
  57. boule_de_poils = Chat("Boule de Poils")
  58. boule_de_poils.caresse()
  59. # affiche: Boule de Poils fait "prrrrr"
  60. Ensuite, on peut rajouter la méthode ``console()`` dans la classe Enfant,
  61. qui va:
  62. * récupérer l'instance de la classe Chat dans ``self`` - comme n'importe quel attribut
  63. * puis appeler la méthode ``caresse()`` de cette instance::
  64. class Enfant:
  65. def __init__(self, prénom, chat):
  66. self.prénom = prénom
  67. self.chat = chat
  68. def console(self):
  69. self.chat.caresse()
  70. Si on combine ces deux classes dans le même morceau de code et qu'on
  71. exécute les instructions suivantes::
  72. boule_de_poils = Chat("Boule de Poils")
  73. alice = Enfant("Alice", boule_de_poils)
  74. alice.console()
  75. On afffichera ```Boule de Poils fait "prrr"`` et alice sera consolée.
  76. On dit parfois qu'on a *délégué* l'implémentation de la méthode ``console()`` de la classe Enfant
  77. à la méthode ``caresse()`` de la classe Chat.