2017-03-24 25 views

回答

3

您可以使用任何具有類方法(或類似方法)的語言來做的事情之一是提供替代構造函數。下面稍微做作Python3例如:

class Color(): 
    def __init__(self, red, green, blue): 
     self._red, self._green, self._blue = red, green, blue 

    @classmethod 
    def by_name(cls_, color_name): 
     color_defs = {'white':(255,255,255), 'red':(255,0,0), 
         'green':(0,255,0),'blue':(0,0,255)} 
     return cls_(*color_defs[color_name]) 

這一類,你現在可以做的:

red = Color(255,0,0) # Using the normal constructor 
    # or 
    red = Color.by_name('red') # Using the alternative 

在Python的「by_name」的方法通常被稱爲工廠方法,而不是一個構造函數,但它使用正常的構造函數方法。

因爲'by_name'方法只是一個類方法,所以它意味着你繼承它,類方法也被繼承 - 所以它可以在任何子類上使用:即它是可繼承和可擴展的。

在一個延伸的Color類的上方,並延伸的構造和「by_name」

class ColorWithAlpha(Color): 
     def __init__(self, red, green, blue, alpha): 
      super().__init__(red,green,blue) 
      self._alpha = alpha 

     @classmethod 
     def by_name(cls_, color_name, alpha): 
      inst = Color.by_name(color_name): 
      inst._alpha = alpha 
      return inst 

red_alpha = ColorWithAlpha(255,0,0,0.5) 
red2_alpha = ColorWithAlpha.by_name('red',0.5) 

其他的語言也有類似的替代構造(例如C++的子類的Python的一個例子允許基於多個構造參數類型),並且這些方法都是可繼承的(即子類也可以使用它們(或根據需要擴展它們)。 我不能說其他語言,但我確信其他OOP語言將具有類似的構造函數/工廠方法功能。

+1

@martineau:感謝編輯 - 良好的捕獲。 –

+1

不客氣。我也贊成你的答案。 – martineau

2

Python類只能有一個是__init__()方法,它被許多人稱爲類構造函數,因爲它被稱爲在通過調用類創建類時初始化類的實例。

有時是有用的創建類的實例的其他替代方案,方式,以及這樣做函數或方法可以統稱爲替代構造。由於這些將在實例存在之前調用,因此它們通常實現爲classmethod s,而不是獨立函數。這還需要使用類名(或類的實例)使其更加明顯:即MyClass.created_some_other_way()

與大多數方法一樣,它們將由定義它們的類派生的任何子類繼承,因此可以統稱爲可繼承的替代構造函數強調否則將隱含的內容。

+0

@martineua。謝謝您的回答。這讓我想起了幾個月前的一個問題。如果構造函數需要其他類,則有時不可能更改(可選)構造函數使用的類。如果你好奇,這裏是一個問題:http:// stackoverflow。com/questions/27571848/name-of-design-pattern-get-class-class-level – guettli

+1

@guettli:認識到任何替代構造函數(無論它們是獨立函數還是可能繼承的classmethods)結束都很重要調用「真實」類構造函數「__init __()」。這意味着如果已經爲它實現了一些方案('__init __()')以使用不同的類,那麼該方案也將被由替代方式創建的實例使用。換句話說,其他問題中顯示的設計模式也可以與(可能繼承的)替代構造函數一起使用。 – martineau

+0

謝謝......並且:你有沒有275問題設計模式的名字? – guettli