簡體   English   中英

Python:重疊(非獨占)繼承以提供基於實例參數的方法

[英]Python: overlapping (non exclusive) inheritance to have methods available based on instance parameters

如果參數滿足特定條件,我希望某些屬性和方法僅在類實例中可用。 不同的情況不是唯一的。 我已經有了一個可行的解決方案(包括 ShadowRanger 的建議):

class polygon():
    def __new__(cls, vert, axis=None):
        triangle = vert == 3
        solidrev = axis is not None
        if triangle and not solidrev:
            return super().__new__(_triangle)
        elif solidrev and not triangle:
            return super().__new__(_solid)
        elif solidrev and triangle:
            return super().__new__(_triangle_solid)
        else:
            return super().__new__(cls)
    def __init__(self, vert, axis=None):
        self.polygon_attribute = 1
    def polygon_method(self):
        print('polygon')

class _triangle(polygon):
    def __init__(self, vert, axis=None):
        super().__init__(vert, axis)
        self.triangle_attribute = 2
    def triangle_method(self):
        print('triangle')

class _solid(polygon):
    def __init__(self, vert, axis):
        super().__init__(vert, axis)
        self.solid_attribute = 3
    def solid_method(self):
        print('solid of revolution')

class _triangle_solid(_triangle, _solid):
    def __init__(self, vert, axis):
        super().__init__(vert, axis)

屬性和方法的可用性取決於實例參數:

  • 基類的屬性和方法應該始終可用。
  • 如果第一個參數等於 3,則子類 _triangle 的屬性和方法應該可用。
  • 如果定義了第二個參數,子類 _solid 的屬性和方法應該可用。

所有組合:

P = polygon(2)
P = polygon(2,axis=0)
P = polygon(3)
P = polygon(3,axis=0)

有沒有更優雅的方法來做到這一點? 在理想情況下,我想擺脫 _triangle_solid 類。 另外,我不明白為什么我需要在某些情況下而不是所有情況下為 axis 定義默認參數。

完整項目: https ://github.com/gerritnowald/polygon

這是一個試圖過度使用繼承的例子。 當子類與其父類之間存在“是”關系時,繼承在邏輯上是有意義的。 三角形是多邊形,所以沒有問題; 這是一個合理的繼承鏈。 旋轉實體雖然可能由多邊形構建,但它不是多邊形,並且試圖將其楔入繼承層次結構會產生問題。 更糟糕的是,旋轉實體甚至可能根本無法根據多邊形來定義。

我強烈建議使用代表正在旋轉以產生它的任何屬性來定義您的旋轉實體,而不是作為該旋轉圖形的子類。


話雖如此, polygon本身不應該負責知道它的所有子類,如果是,它仍然應該是三角形的父類。 您當前呈現的設計有一個polygon類,沒有任何東西是其實例; __new__返回的不是polygon的東西,這讓人很困惑。 您可以通過以下方式以更安全的方式編寫層次結構,即使仍然不是慣用的 OO 方式:

# Tweaked name; it's not just the base anymore; using PEP8 class name capitalization rules
class Polygon:
    def __new__(cls, vert, *args, **kwargs):  # Accept and ignore the arguments we don't care
                                              # about, __init__ will handle them
        if vert == 3:
            return super().__new__(Triangle)
        else:
            return super().__new__(cls)

    def __init__(self, vert, axis):
        self.polygon_attribute = 1

    def polygon_method(self):
        print('polygon')

class Triangle(Polygon):
    def __init__(self, vert, axis):
        super().__init__(vert, axis)
        self.triangle_attribute = 2

    def triangle_method(self):
        print('triangle')

t = Polygon(3, None)
p = Polygon(4, None)
print(type(t), type(p))
# Indicates t is a Triangle, p is a Polygon

在線試用!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM