【问题标题】:How should I implement, and what should I call, a common base class for Area and Point?我应该如何实现 Area 和 Point 的公共基类,我应该称之为什么?
【发布时间】:2016-07-19 10:50:01
【问题描述】:

所以我想要一个Point 和一个Area 类,类似于C# 的PointSize。下面是这两个类的简单实现:

class Point:
    def __init__(self, x=0, y=0):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    # Many other magic methods too!


class Area:
    def __init__(self, width=0, height=0):
        self.width = width
        self.height = height

    def __add__(self, other):
        return Area(self.width + other.width, self.height + other.height)

    # Many other magic methods too!

如您所见,这两个类完全相同,除了一个有 x, y 而另一个有 width, height

为这两者实现某种基类有什么好的解决方案?

【问题讨论】:

  • @Lucian 可能是因为 “正如你所看到的,这两个类是完全相同的,除了一个有 x, y 而另一个有 width, height。” 一个基类摆脱多个类中的重复代码。不是说这是最好的解决方案,而是a解决方案。
  • 它们在构造中每个都需要两个参数,但这并不一定会使它们相关到足以证明公共父类的合理性。
  • @TigerhawkT3 他们都有大约 10 个共同的方法,它们做的事情完全相同......只是两个属性的名称不同......
  • 这是真的 Markus,你的回答还可以,但代码总是应该非常直观且易于阅读,但那是另一回事了
  • @MarkusMeskanen 是的,这就是我的想法。

标签: python python-3.x subclass base-class


【解决方案1】:

如果您不介意使用不可变对象,您可以继承 tuple 来为所有二维材料创建一个基类:

class _2dTuple(tuple):

     def __new__(cls, hor=0, ver=0):
         super().__new__(cls, (hor, ver))

     def __add__(self, other):
         return type(self)(self[0] + other[0], self[1] + other[1])

现在,当您将_2dTuple 子类化时,您可以为您的x, ywidth, height 创建property getter:

class Point(_2dTuple):

    @property
    def x(self):
        return self[0]

    @property
    def y(self):
        return self[1]


class Area(_2dTuple):

    @property
    def width(self):
        return self[0]

    @property
    def height(self):
        return self[1]

【讨论】:

  • 我不是数学家,但点是“二维的东西”吗?它们可以存在于任何维度结构中,但它们本身没有“大小”。此外,您的解决方案为两个对象都提供了一个父类,但这样做的代价是用不太清晰的内部变量(例如self[0])来支持清晰的内部变量(例如self.width)。我想如果你将它扩展到 n 维对象是有意义的,因为我们没有超出标准三个维度(长度、宽度、高度)的名称,但对于 2D 对象,我认为常规命名约定可能更可取.
  • 感谢您的回答,如果有人发现更好的东西,我仍然会在接受之前等待更多答案! :)
  • @TigerhawkT3 你是对的,这取决于一个人如何定义“东西”,这对我来说是相当模棱两可的措辞。显然,像widthheight 这样清晰的名称比通过索引访问变量要好,但是由于我们在一个名为2dTuple 的类中,它是元组的子类,我不认为通过索引访问属性01 太复杂以至于无法理解,即使写下来并不漂亮。 OP 的问题围绕着不将值绑定到名称,因为他希望不同类中的属性有不同的名称。
  • 请注意,此实现不会阻止 Area() + Point() 的发生。这可能是也可能不是你想要的,但至少对我来说这没有任何意义。
  • @JonasWielicki 为什么要明确停止它?这是 Python,如果您将区域和点附加在一起,那是您自己的错。我也可以在 Python 中将拖拉机和区域附加在一起,因为它们恰好都有 widthheight(如果我通常实现 Area 而不是这个元组子类)。这有多大意义?
猜你喜欢
  • 2017-09-13
  • 2021-03-24
  • 2014-03-15
  • 1970-01-01
  • 2023-04-02
  • 1970-01-01
  • 2013-09-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多