【问题标题】:How to assign a data attribute of a subclass to attributes of its parent class如何将子类的数据属性分配给其父类的属性
【发布时间】:2021-05-11 14:27:27
【问题描述】:

我有一个带有数据属性宽度和高度的矩形类,我想要一个带有数据属性 side_length 的子类 Square。

如何让 square.width 和 square.height 给出它的边长?即与 square.side 相同

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

class Square(Rectangle):
    def __init__(self, side)
        self.side = side

这是我目前所拥有的。

【问题讨论】:

  • 这句话是什么意思? "square.width 和 square.height 给出它的边长"
  • 对于 Square 类的一个实例(我也称它为 square),当我使用 square.width 或 square.height 返回数据属性宽度和高度时,它们是父级的属性类 Rectangle,我希望这些返回与 square.side 相同的值(其中 square 是类 Square 的属性),因为正方形的边长对于宽度和高度是相同的

标签: python class subclass


【解决方案1】:

你可以调用 Rectangle 的构造函数。

super(Square,self).__init__(side, side)

或者您可以拥有返回这些属性的属性。我会走向超级。

@property
def length(self):
   return self.side

@property
def width(self):
   return self.side

如果您可以在创建对象后更改sideheightwidth 属性,事情会变得更加复杂。您需要保持widthheight 同步和连贯。一种可能的方法是完全取消 side 作为 Square 上的存储属性,而是将其作为可更新 Rectangle 宽度和高度的读写属性。

在初始构造函数之后保持高度/宽度/边排序:


class Rectangle:

    @property
    def height(self):
        return self._height

    @height.setter
    def height(self, value):
        self._height = value

    @property
    def width(self):
        return self._width

    @width.setter
    def width(self, value):
        self._width = value

    def __repr__(self):
        return(f"{self.__class__.__name__}:{self.height=} {self.width=}")

    def __init__(self, height, width):
        self.height = height
        self.width = width

class Square(Rectangle):

    def __repr__(self):
        return(f"{self.__class__.__name__}:{self.side=}")

    @property
    def side(self):
        return self._width

    @side.setter
    def side(self, value):
        self._width = value
        self._height = value

    def __init__(self, side):
        super(Square, self).__init__(side, side)

    #these are here so you can't cheat and vary height and width
    #independently on a square
    @property
    def width(self):
        return self.side

    @width.setter
    def width(self, value):
        self.side = value

    @property
    def height(self):
        return self._side

    @height.setter
    def height(self, value):
        self.side = value



rectangle = Rectangle(5,2)
print(rectangle)
rectangle.height = 6
print(rectangle)

square = Square(3)
print(square)
square.side = 6
print(square)
square.height = 9
print(square)

输出:

$ py test_square.py
Rectangle:self.height=5 self.width=2
Rectangle:self.height=6 self.width=2
Square:self.side=3
Square:self.side=6
Square:self.side=9

【讨论】:

  • 我希望能够在创建后更改边长属性,因为我在矩形类上定义了更改宽度和高度的方法。有关如何执行此操作的任何指示?
  • @ogprog:如果能够在构造后独立地重新配置边长是 Rectangle 类的一个特性,那么你的 Square 会破坏 Liskov 替换 - 你不能用 Square 做你可以做的事情带一个矩形。在这种情况下,您的 Square 类不应该是 Rectangle 子类,或者您应该从 Rectangle 中删除边长重新配置功能。
  • @user2357112supportsMonica 不一定。如果您认为改变 Square 的宽度或高度与改变边 并相应地编写属性 相同,那么您不会破坏 LSP。这就是我在这里所做的。总体思路是好的 OOP 吗?嗯,完全不确定,但至少一个正方形仍然是一个正方形在这个特殊的受限场景中,我对我很少使用的 setter 感到很开心。
  • @JLPeyret 太好了,谢谢!我认为这是因为我们可以达到我正在尝试构建的程序的规范,同时仍然保留 Square 上的高度设置器方法
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-21
  • 1970-01-01
  • 2021-12-20
相关资源
最近更新 更多