1

I would like to build a class and subclasses where the subclasses inherit some methods and from the superclass.

Nothing special so far, but I would like to be able to create subclasses depending on a parameter e.g. a = Shape(sides=3, base=2, height=12) which should result in the same as c = Triangle(base=2, height=2) in the sample code:

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())

Which throws an error TypeError: __new__() missing 1 required positional argument: 'sides'.

when I do not inherit the class (do class Triangle:) it down not throw the error but of course I cannot use the function a anymore...

Any hints? My solutions so far were based on https://stackoverflow.com/a/60769071, https://stackoverflow.com/a/61509283 and https://www.code-learner.com/how-to-use-python-new-method-example/

One possibility is maybe the use of a Factory pattern but I really liked the idea of overwriting the new function...

martineau
  • 119,623
  • 25
  • 170
  • 301
qwertz
  • 46
  • 8
  • Check out [here](https://stackoverflow.com/questions/18680901/why-does-or-rather-how-does-object-new-work-differently-in-these-two-cases) and [here](https://stackoverflow.com/questions/19277399/why-does-object-new-work-differently-in-these-three-cases) and [here](https://stackoverflow.com/questions/28236516/python-subclassing-a-class-with-custom-new) – cajomar Aug 07 '20 at 14:38

2 Answers2

2

You are inheriting the Shape class in the Triangle & Square classes, which will result in infinite recursive calls to __new__ of Shape class.

Have modified your code a little with a Factory class to achieve it.

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())
MukeshRKrish
  • 1,040
  • 5
  • 14
1

Your Triangle class is inheriting the __new__ method of its superclass Shape which requires the side argument. You could either override this method in each subclass or make a new Factory class ShapeFactory which returns different shapes.

Lcj
  • 371
  • 3
  • 10
  • I already tried that using ```python def __new__(cls, *args, **kwargs): pass ``` in the Triangle class which results in a None object. I think I have to return an object there correct? But which one? – qwertz Aug 07 '20 at 14:41
  • Yes, the `__new__` method of the `Triangle` class must return an object. – Lcj Aug 08 '20 at 14:11
  • But which one? I think in each case I run into some loops... – qwertz Aug 09 '20 at 16:52