2009-02-09 2 views
4

Я следующий пример кода:Могу ли я создать экземпляр объекта подкласса от суперкласса

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 

При использовании следующих может быть сгенерированы:

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

Теперь позволяет сказать, у меня есть еще несколько подклассов class C(A): и class D(A):. Я также знаю, что идентификатор всегда будет соответствовать либо B, C, либо D, но никогда в двух из них одновременно.

Теперь я хотел бы назвать A (23) и получить объект правильного подкласса. Что-то вроде этого:

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

Является ли это невозможно или возможно, но просто плохой дизайн? Как решить такие проблемы?

ответ

6

Вам следует скорее реализовать Abstract Factory pattern, и ваш завод будет строить любой объект, который вам нравится, в зависимости от предоставленных параметров. Таким образом, ваш код останется чистым и расширяемым.

Любой взлом, который вы можете использовать для его непосредственного использования, может быть удален при обновлении версии интерпретатора, поскольку никто не ожидает обратной совместимости для сохранения таких вещей.

EDIT: Через некоторое время я не уверен, следует ли использовать абстрактную фабрику, или Factory Method pattern. Это зависит от деталей вашего кода, так что это соответствует вашим потребностям.

2

Как правило, это не такая хорошая идея, когда суперкласс имеет какое-либо знание подклассов.

Подумайте, что вы хотите сделать с точки зрения OO.

Суперкласс обеспечивает общее поведение для всех объектов этого типа, например. Animal. Затем подкласс обеспечивает специализацию поведения, например. Собака.

Подумайте об этом с точки зрения отношения «isa», то есть собака является животным.

An Animal is Dog Собака на самом деле не имеет смысла.

НТН

веселит,

Роб

2

Я не думаю, что вы можете изменить тип объекта, но вы можете создать еще один класс, который будет работать как фабрика для подклассов. Что-то вроде этого:

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

Я не уверен, почему LetterFactory должен быть классом. Определив его как функцию 'letter_factory', можно было бы упростить (например, не нужно отвечать на вызовы' LetterFactory.getLetterObject', просто вызовы 'letter_factory') – tzot

Смежные вопросы