Python Forum
Problems with super() - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Problems with super() (/thread-41932.html)



Problems with super() - Hoespilaar - Apr-10-2024

Hi, I've been working on a game that requires classes and subclasses. In order to keep some sort of structure, I wanted to put them in different files. Of course with subclasses comes the super() keyword. For single inheritance this does not pose a problem. But when it comes down to multiple inheritance I can't wrap my head around it.

In BaseClasses.py are all the classes most other classes inherit from. The ones in my problem all inherit from Object:
class Object:
    x = 0
    y = 0

    def __init__(self, x, y) -> None:
        self.x = x
        self.y = y
All the visual classes are contained in Shapes.py. The important ones here are Rectangle and its base Shape
class Shape(BaseClasses.Object):
    def __init__(self, x, y) -> None:
        super().__init__(x, y)

class Rectangle(Shape):
    size_x = 0
    size_y = 0
    color = (0, 0, 0)

    def __init__(self, x, y, size_x, size_y, color) -> None:
        super().__init__(x, y)
        self.size_x = size_x
        self.size_y = size_y
        self.color = color
Lastly there's CollisionObjects.py, where the problem occurs.
class Collision_Object(BaseClasses.Object):
    collider_size_x = 0
    collider_size_y = 0

    def __init__(self, x, y, collider_size_x, collider_size_y):
        super().__init__(x, y)
        self.collider_size_x = collider_size_x
        self.collider_size_y = collider_size_y

class Static_Object(Collision_Object, Shapes.Rectangle):
    Color = (255, 0, 0)

    def __init__(self, x, y, size_x, size_y):
        print(Static_Object.__mro__)
        super().__init__(x, y, size_x, size_x)
        super().__init__(x,y, size_x, size_y, self.Color)
I call the Static_Object class from the main game code with the line
StaticObject = CollisionObjects.Static_Object(400, 300, 40, 40)
I've tried a lot of different ways of using super() in the Static_Object class, but none of them seem to work. The way I've got it set up now gives me the following error:
Quote:Exception has occurred: TypeError
Rectangle.__init__() missing 3 required positional arguments: 'size_x', 'size_y', and 'color'
File "C:\Users\Manu Coppieters\Documents\Tomb of the mask\CollisionObjects.py", line 11, in __init__
super().__init__(x, y)
File "C:\Users\Manu Coppieters\Documents\Tomb of the mask\CollisionObjects.py", line 28, in __init__
super().__init__(x, y, size_x, size_x)
File "C:\Users\Manu Coppieters\Documents\Tomb of the mask\Game.py", line 18, in <module>
StaticObject = CollisionObjects.Static_Object(400, 300, 40, 40)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: Rectangle.__init__() missing 3 required positional arguments: 'size_x', 'size_y', and 'color'

The weird thing here is that line 11 in CollisionObjects.py is the super().__init__() line in the Collision_Object class. It doesn't inherit from Rectangle, yet it appears to try and initialize it. Writing this out, it makes me think there might be a problem with the MRO?

Anyways, any help is appreciated.


RE: Problems with super() - Gribouillis - Apr-10-2024

I think multiple inheritance should be used warily and possibly not at all, an exception being the case of mixin classes.

In your code, the intention behind the classes is not obvious, so it is difficult to give a clear advice. However, remember that inheritance means the ISA relationship, but in your case, I'd tend to believe that the StaticObject is a CollisionObject having a certain shape. Its relation to shape is more HAS-A shape than IS-A shape. If this is true, you could replace inheritance with composition, which is usually considered a better design. So you would write the class as
class StaticObject(Collision_Object):
    Color = (255, 0, 0)
 
    def __init__(self, x, y, size_x, size_y):
        print(Static_Object.__mro__)
        super().__init__(x, y, size_x, size_x)
        self.shape = Shapes.Rectangle(x,y, size_x, size_y, self.Color)
If you insist on using multiple inheritance, you could do this for example
class StaticObject(CollisionObject, Shapes.Rectangle):
    Color = (255, 0, 0)
 
    def __init__(self, x, y, size_x, size_y):
        print(StaticObject.__mro__)
        super().__init__(x, y, size_x, size_x)
        Shapes.Rectangle.__init__(self, x,y, size_x, size_y, self.Color)
Also have a look at PEP8 with regards to class naming conventions. Of course, PEP8 is not mandatory.


RE: Problems with super() - Hoespilaar - Apr-10-2024

(Apr-10-2024, 08:39 AM)Gribouillis Wrote: I think multiple inheritance should be used warily and possibly not at all, an exception being the case of mixin classes.

In your code, the intention behind the classes is not obvious, so it is difficult to give a clear advice. However, remember that inheritance means the ISA relationship, but in your case, I'd tend to believe that the StaticObject is a CollisionObject having a certain shape. Its relation to shape is more HAS-A shape than IS-A shape. If this is true, you could replace inheritance with composition, which is usually considered a better design...

Thank you for your reply. I originally structured my code with IS-A relations, but in the example code my professor gave me there were a lot of HAS-A relations, hence why I changed it. I think I will revert my code back to the IS-A relations I used to have.

Thank you for your help!


RE: Problems with super() - kanetracy - Jun-11-2024

The response is much appreciated. I switched to an IS-A relational structure for my code because my professor provided an example with a lot of HAS-A relations. The IS-A relations that were previously in my code are what I'm going to use again. Link Removed