2012-05-26 3 views
1

Cette question concerne environ héritage Python mais est expliqué avec un exemple Django, cela ne devrait pas blesser si.Utiliser une méthode d'autres classes sans héritage

Je possède ce modèle Django, avec Page et RichText modèles ainsi:

class Gallery(Page, RichText): 
    def save(self, *args, **kwargs): 
     # lot of code to unzip, check and create image instances. 
     return "something" 

Je suis seulement intéressé à utiliser la méthode save dans une autre classe.

Une solution pourrait être:

class MyGallery(models.Model): 
    def save(self, *args, **kwargs): 
     # here goes the code duplicated from Gallery, the same. 
     return "something" 

Je voudrais éviter la duplication de code et aussi je ne suis pas intéressé par les membres héritant de Page et RichText (donc je ne veux pas faire class MyGallery(Gallery):. Si ce serait légal j'écrire quelque chose comme ceci:

class MyGallery(models.Model): 
    # custom fields specific for MyGallery 
    # name = models.CharField(max_length=50) 
    # etc 

    def save(self, *args, **kwargs): 
     return Gallery.save(self, *args, **kwargs) 

Mais ça ne marchera pas parce que le save() en Gallery attend une instance de Gallery, non MyGallery .

N'importe quel moyen de "détacher" la méthode save() de Gallery et de l'utiliser dans MyGallery tel qu'il y était défini?

EDIT:

J'oubliais de dire que Gallery est donnée et ne peut pas être changé.

Répondre

2

Vous pouvez accéder à la __func__ attribute of the save method:

class Gallery(object): 
    def save(self, *args, **kwargs): 
     return self, args, kwargs 

class MyGallery(object): 
    def save(self, *args, **kwargs): 
     return Gallery.save.__func__(self, *args, **kwargs) 
    # or 
    # save = Gallery.save.__func__ 

mg = MyGallery() 
print mg.save('arg', kwarg='kwarg') 
# (<__main__.MyGallery object at 0x04DAD070>, ('arg',), {'kwarg': 'kwarg'}) 

mais vous êtes mieux refactoring si possible:

class SaveMixin(object): 
    def save(self, *args, **kwargs): 
     return self, args, kwargs 

class Gallery(SaveMixin, object): 
    pass 

class MyGallery(SaveMixin, object): 
    pass 

ou

def gallery_save(self, *args, **kwargs): 
    return self, args, kwargs 

class Gallery(object): 
    save = gallery_save 

class MyGallery(object): 
    save = gallery_save 
0

Je ne sais pas pourquoi vous êtes contre l'héritage, notamment en ce qui concerne les méthodes. Je crée régulièrement une classe MixIn qui est héritée par tous mes Django models.Model, et elle contient toutes sortes de méthodes utiles pour la création d'URL, dumps, etc., etc. Je rends les méthodes défensives en ce qu'elles utilisent hasattr() pour s'assurer qu'elles appliquer à une classe particulière, mais cela est un gain de temps réel.

+0

Je ne suis pas contre l'héritage en général, mais dans ce cas je suis. Si 'MyGallery' hériterait de' Gallery', la sous-classe aurait des méthodes que je n'utiliserais jamais, donc il me semble absurde d'avoir quelque chose que vous n'utilisez pas mais qui nécessite aussi de la mémoire. Ensuite, pour le fonctionnement de Django, les classes héritées contribueraient également en termes de nouveaux champs de base de données (inutiles dans mon scénario). – Paolo

+0

Enfin, les mixins ne s'intègrent pas bien car je ne peux pas changer la classe 'Gallery'. – Paolo

+1

@Guandalino: Je reconnais que ce n'est pas ce que vous voulez faire, mais je ne crois pas que les méthodes Python héritées d'autres classes prennent plus de place qu'un simple pointeur de la classe enfant vers la classe parente. En ce qui concerne les champs DB, je suis entièrement d'accord avec vous. J'ai essayé de le faire à quelques reprises et c'était a) maladroit, b) non intuitif. Bonne chance. –

Questions connexes