【问题标题】:Subclassing, inheriting and subclass picking子类化、继承和子类选择
【发布时间】:2020-08-07 14:27:39
【问题描述】:

我想构建一个类和子类,其中子类从超类继承一些方法。

到目前为止没有什么特别的,但我希望能够根据参数创建子类,例如a = Shape(sides=3, base=2, height=12) 应该与示例代码中的 c = Triangle(base=2, height=2) 相同:

class Shape:
    def __new__(cls, sides, *args, **kwargs):
        if sides == 3:
            print('a')
            return Triangle(*args, **kwargs)
        else:
            return Square(*args, **kwargs)

    def __init__(self, a):
        self._a = a

    @property
    def a(self):
        return self._a


class Triangle(Shape):
    def __init__(self, base, height):

        super().__init__(self, a='triangle')
        self.base = base
        self.height = height

    def area(self):
        return (self.base * self.height) / 2


class Square(Shape):
    def __init__(self, length):
        Shape.__init__(self, a='square')
        self.length = length

    def area(self):
        return self.length * self.length


a = Shape(sides=3, base=2, height=12)
b = Shape(sides=4, length=2)

c = Triangle(base=2, height=2)

print(c.a)

print(str(a.__class__))
print(a.area())

print(str(b.__class__))
print(b.area())

这会引发错误TypeError: __new__() missing 1 required positional argument: 'sides'

当我不继承类(做class Triangle:)时,它不会抛出错误,但我当然不能再使用函数a...

有什么提示吗?到目前为止,我的解决方案是基于 https://stackoverflow.com/a/60769071https://stackoverflow.com/a/61509283https://www.code-learner.com/how-to-use-python-new-method-example/

一种可能是使用工厂模式,但我真的很喜欢覆盖 new 函数的想法...

【问题讨论】:

标签: python python-3.x inheritance subclass


【解决方案1】:

您的Triangle 类继承了其超类Shape__new__ 方法,该方法需要side 参数。 您可以在每个子类中重写此方法,也可以创建一个新的 Factory 类 ShapeFactory,它返回不同的形状。

【讨论】:

  • 我已经尝试在 Triangle 类中使用 python def __new__(cls, *args, **kwargs): pass ,这会导致 None 对象。我想我必须在那里正确返回一个对象?但是哪一个?
  • 是的,Triangle 类的__new__ 方法必须返回一个对象。
  • 但是哪一个?我认为在每种情况下我都会遇到一些循环......
【解决方案2】:

您正在继承TriangleSquare 类中的Shape 类,这将导致对__new__Shape 类的无限递归调用。

已使用 Factory 类稍微修改了您的代码以实现它。

class Shape:
    def __init__(self, a):
        self._a = a

    @property
    def a(self):
        return self._a

class ShapeFactory:
    def __new__(cls, sides, *args, **kwargs):
        if sides == 3:
            print('a')
            return Triangle(*args, **kwargs)
        else:
            return Square(*args, **kwargs)


class Triangle(Shape):
    def __init__(self, base, height):

        super().__init__(a='triangle')
        self.base = base
        self.height = height

    def area(self):
        return (self.base * self.height) / 2


class Square(Shape):
    def __init__(self, length):
        Shape.__init__(self, a='square')
        self.length = length

    def area(self):
        return self.length * self.length


a = ShapeFactory(sides=3, base=2, height=12)
b = ShapeFactory(sides=4, length=2)

c = Triangle(base=2, height=2)

print(c.a)

print(str(a.__class__))
print(a.area())

print(str(b.__class__))
print(b.area())

【讨论】:

  • 当然,没有什么理由让ShapeFactory 成为一个类而不是一个常规函数。
  • 你的意思是“全局”函数还是超类中的一个?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-09
  • 1970-01-01
相关资源
最近更新 更多