mardi 19 juin 2018

Decorator enhancing method internally called

I want to write a decorator that is able to modify a function called by the concrete component, the following code sample illustrates my problem:

In [2]: class Animal:
   ...:     def sound(self):
   ...:         raise NotImplementedError
   ...:         
   ...:     def speak(self):
   ...:         print(self.sound())
   ...:         

In [3]: class Dog(Animal):    
   ...:     def sound(self):
   ...:         return 'woof!'
   ...:     

In [4]: class Bigfy:
   ...:     def __init__(self, animal):
   ...:         self.animal = animal
   ...:         
   ...:     def sound(self):
   ...:         return self.animal.sound().upper()
   ...:     
   ...:     def speak(self):
   ...:         return self.animal.speak()
   ...:     

In [5]: dog = Dog()
   ...: dog.speak()
   ...: 
woof!

In [6]: big_dog = Bigfy(Dog())
   ...: big_dog.sound()
   ...: 
Out[6]: 'WOOF!'

In [7]: big_dog.speak()
woof! # I want 'WOOF!' here

The method that I want to enhance functionality is sound, but this method is not directly called by the client and is instead internally called by speak so all the wraps on sound take no effect.

Is it possibly to achieve what I want using the decorator design pattern? If not what design pattern I should take a look?

Additional info: I tried swapping the wrapped class sound reference to the wrapper sound method, that worked but I found it was a very bad solution.

Aucun commentaire:

Enregistrer un commentaire