2009-02-09 95 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):。我也知道id始終適合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,然後您的工廠將根據提供的參數構建您喜歡的任何對象。這樣你的代碼將保持乾淨和可擴展。

當你升級你的解釋器版本時,你可以直接使用的任何破解都可以被刪除,因爲沒有人需要向後兼容性來保存這些東西。

編輯:一段時間後,我不知道你是否應該使用抽象工廠,或Factory Method pattern。這取決於您的代碼的細節,以滿足您的需求。

2

當超類具有子類的任何知識時,通常不是一個好主意。

從OO的角度思考你想做什麼。

超類爲所有類型的對象提供共同行爲,例如,動物。然後,該子類提供行爲的專門化,例如狗。

從「isa」關係的角度考慮,即狗是動物。

動物是一隻狗並不真正有意義。

HTH

歡呼聲,

羅布

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 2009-10-27 10:04:55