2009-02-09 10 views
4

Je le code exemple suivant:Puis-je instancier un objet sous-classe de la superclasse

class A(object): 
    def __init__(self, id): 
     self.myid = id 
    def foo(self, x): 
     print 'foo', self.myid*x 

class B(A): 
    def __init__(self, id): 
     self.myid = id 
     self.mybid = id*2 
    def bar(self, x): 
     print 'bar', self.myid, self.mybid, x 

Lorsqu'ils sont utilisés, les éléments suivants pourraient être générés:

>>> a = A(2) 
>>> a.foo(10) 
foo 20 
>>> 
>>> b = B(3) 
>>> b.foo(10) 
foo 30 
>>> b.bar(12) 
bar 3 6 12 

Maintenant, supposons que j'ai d'autres sous-classes class C(A): et class D(A):. Je sais aussi que l'identifiant va toujours dans B, C ou D, mais jamais dans deux d'entre eux en même temps.

Maintenant, je voudrais appeler A (23) et obtenir un objet de la sous-classe correcte. Quelque chose comme ceci:

>>> type(A(2)) 
<class '__main__.B'> 
>>> type(A(22)) 
<class '__main__.D'> 
>>> type(A(31)) 
<class '__main__.C'> 
>>> type(A(12)) 
<class '__main__.B'> 

Est-ce impossible ou est-il possible mais juste une mauvaise conception? Comment de tels problèmes devraient-ils être résolus?

Répondre

6

Vous devriez plutôt implémenter Abstract Factory pattern, et votre usine construirait alors n'importe quel objet que vous aimez, en fonction des paramètres fournis. De cette façon, votre code restera propre et extensible.

Tout hack que vous pourriez utiliser pour le faire directement peut être retiré lorsque vous mettez à niveau votre version d'interpréteur, puisque personne ne s'attend à une rétrocompatibilité pour préserver de telles choses.

EDIT: Après un moment, je ne suis pas sûr que vous devriez utiliser Abstract Factory, ou Factory Method pattern. Cela dépend des détails de votre code, alors répondez à vos besoins.

2

Généralement ce n'est pas une bonne idée quand une super-classe a une connaissance des sous-classes. Pensez à ce que vous voulez faire d'un point de vue OO.

La superclasse fournit un comportement commun pour tous les objets de ce type, par ex. Animal. Ensuite, la sous-classe fournit la spécialisation du comportement, par ex. Chien. Pensez-y en termes d'une relation "isa", c'est-à-dire qu'un chien est un animal.

Un animal est un chien n'a pas vraiment de sens.

HTH

acclamations,

Rob

2

Je ne pense pas que vous pouvez changer le type de l'objet, mais vous pouvez créer une autre classe qui fonctionnera comme une usine pour les sous-classes. Quelque chose comme ceci:

class LetterFactory(object): 
    @staticmethod 
    def getLetterObject(n): 
     if n == 1: 
      return A(n) 
     elif n == 2: 
      return B(n) 
     else: 
      return C(n) 

a = LetterFactory.getLetterObject(1) 
b = LetterFactory.getLetterObject(2) 
... 
+0

Je ne sais pas pourquoi LetterFactory doit être une classe. Le définir comme une fonction 'letter_factory' rendrait les choses plus faciles (par exemple pas besoin d'appels' LetterFactory.getLetterObject', juste des appels 'letter_factory') – tzot

Questions connexes