Wiki Python Fr   Delegation UserPreferences
 
HelpContents FindPage Diffs Info Edit Subscribe XML Print View

La composition( ou l'aggrégation) avec délégation permet d'étendre un objet sans introduire le couplage fort induit par l'héritage. C'est la base de plusieurs [WWW]Design Pattern, dont notamment le pattern Decorateur (NB : ne pas confondre avec les DecorateurDeFonction de Python).

Python propose un mécanisme très souple de délégation, via les méthodes 'magiques' getattr() et setattr().

La première est appelée quand l'attribut demandé n'est pas trouvé via le mécanisme de résolution normal, et prend en argument le nom de l'attribut.

La seconde est plus délicate à mettre en oeuvre, puisque si implémentée, elle est systématiquement appelée. Il convient donc d'être attentif pour éviter une récursion infinie. La méthode consiste usuellement à appeler explicitement la méthode getattr de la classe parent.

  1 
  2 
  3 
  4 
  5 
  6 
  7 
  8 
  9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
 25 
 26 
 27 
 28 
 29 
 30 
 31 
 32 
 33 
 34 
 35 
 36 
 37 
 38 
 39 
 40 
class A(object):
  def __init__(self, name):
    self.name = name

  def age_du_capitaine(self):
    return 42

  def dis_bonjour(self):
    return "bonjour de %s" % self.name


class B(object):
  def __init__(self, objA):
    self._objA = objA

  def __getattr__(self, name):
    if name == '_objA':
      raise AttributeError, \
        'object %s has no attribute %s' % \
        (self.__class__.__name__, name)
    # on peut filtrer ici les accès aux attributs 
    return getattr(self._objA, name)

  def __setattr__(self, name, value):
    if name != '_objA' and hasattr(self._objA, name):
      setattr(self._objA, name, value)
    else:
      object.__setattr__(self, name, value)

  # rédéfinir ici les methode de A qu'on veut surcharger
  def age_du_capitaine(self):
    age = self._objA.age_du_capitaine()
    return "le capitaine a %d ans" % age

  # on laisse dis_bonjour() tel que, l'appel sera
  # automatiquement délégué à self._objA


a = A('toto')
b = B(a)


PythonPowered