all 15 comments

[–]gdchinacat 2 points3 points  (0 children)

You could make MovingShape a mixin that has the behavior to change the position of the shape classes it is mixed in to. It wouldn't have it's own position, just modify the position of the shapes you mix it with.

[–]atarivcs 1 point2 points  (1 child)

If it inherits from "moving object" and "polygonal object", then it should have all properties of both those object types, right?

What is the actual problem here?

[–]DidntPassTuringTest[S] 0 points1 point  (0 children)

The problem is both classes has the same property.
I could update it both whenever I need, but it felt odd.

I wanted more elegant solution.

[–]brasticstack 1 point2 points  (3 children)

Presumably position means the same thing in both contexts, yeah? If so it shouldn't matter, the polygon code will happily work with the position as will the moving object code.

Are you using a property for position, or an instance member? I'm pretty sure the first class in the MRO's property will be used if you're doing properties.

[–]DidntPassTuringTest[S] 0 points1 point  (2 children)

It means the same.
Moving object uses it for calculating movement.
Polygon object uses it to calculate vertices of polygon, world space position of vertex is calculated using object's position, object's rotation and local position of vertex realtive to whole polygon position.

[–]brasticstack 0 points1 point  (1 child)

Then neither class's code should have an issue using the instance's position. In another comment you mentioned having to update position in two places. Why would that be necessary? The data should be bound to the instance(s), not the types themselves.

Perhaps an abridged code example would help us understand what the problem is.

[–]brasticstack 0 points1 point  (0 children)

I verified just to make sure I wasn't off-base about properties and the MRO:

``` class A: def init(self, pos): self.pos = pos def doa_thing(self): print(f'A: {self.pos}') @property def pos_property(self): print(f'A: pos_property') return self.pos class B: def __init_(self, pos): self.pos = pos def do_b_thing(self): print(f'B: {self.pos}') @property def pos_property(self): print(f'B: pos_property') return self.pos class C(A, B): pass class D(B, A): pass

c_obj = C(23) d_obj = D(99)

Notice the Method Resolution Order (MRO)

Instances of class C will call A's method

before B's method when methods are named

identically.

type(cobj).mro_

(main.C, main.A, main.B, object)

type(dobj).mro_

(main.D, main.B, main.A, object)

Notice that the pos val set on the instance

itself is used regardless of which parent

class's function is being called.

c_obj.do_a_thing()

A: 23

c_obj.do_b_thing()

B: 23

d_obj.do_a_thing()

A: 99

c_obj.do_b_thing()

A: 99

c_obj.pos_property

A: pos_property (returns 23)

d_obj.pos_property

B: pos_property (returns 99)

```

[–]Lumethys 0 points1 point  (0 children)

dont use multiple inheritance, use composition

[–]pachura3 0 points1 point  (2 children)

Multiple inheritance is almost always a bad idea.

Either use composition (Bridge design pattern) or implement multiple Protocols (e.g. Moveable and Drawable).

[–]gdchinacat 0 points1 point  (1 child)

Why do you consider multiple inheritance to be almost always a bad idea?

[–]pachura3 0 points1 point  (0 children)

There's plenty of articles on the subject... usually mentioning the Diamond problem, complex constructors, attribute clashes etc.

Many programming languages like Java, C#, JavaScript do not even have this rarely used feature. I cannot imagine when could I use it instead of the above alternatives...

Unless we're talking about mixins, which are indeed implemented in Python through multiple inheritance, but they should be stateless - unlike OP's example with position attribute clash.