Reputation: 314
Summary:
I want to create a class that receives an object in init and becomes that object plus some extra functions that the class has. For example, the Flexible class:
class Flexible():
def __init__(self, obj):
self.obj = obj
def be_flexible(self):
print("Do something")
car = Flexible(Car('BMW'))
plane = Flexible(Plane('Boeing 747'))
car.drive()
car.park()
car.be_flexible()
plane.fly()
plane.be_flexible()
Details:
I have a Shape class and many Shapes that inherit from this class.
class Shape():
def __init__(self, x, y, color=(0, 0, 0)):
self.x, self.y = x, y
self.anchor_x, self.anchor_y = 0, 0
self.rotation = 0
self.color = color
class Circle(Shape):
def __init__(self, x, y, r, **kwargs):
super().__init__(x, y, **kwargs)
self.r = r
class Rectangle(Shape):
def __init__(self, x, y, w, h, **kwargs):
super().__init__(x, y, **kwargs)
self.w = w
self.h = h
class Triangle(Shape):
def __init__(self, x, y, x2, y2, x3, y3, **kwargs):
super().__init__(x, y, **kwargs)
self.x2 = x2
self.y2 = y2
self.x3 = x3
self.y3 = y3
The above code is simplified, all objects contain getters, setters, and various methods to change the shapes.
I want to add a method toggle_anchor(), to show/hide the anchor point. All shapes should be able to access this method. Normally I would add this in the class Shape, but these classes come from an external library, so I cannot modify it.
Therefore, I was hoping I could do something like this (note, AnchorShape
has a Circle
inside, which would be plotted to show where the shape's anchor point is):
class AnchorShape():
def __init__(self, object):
self.object = object
self.anchor_shape = Circle(self.object.anchor_x + self.object.x,
self.object.anchor_y + self.object.y, 1)
def toggle_anchor(self):
...
where the following code will work:
circle = AnchorShape(Circle(x, y, r))
print(f"Created circle (radius:{circle.r}")
square = AnchorShape(Rectangle(x, y, s, s))
print(f"Created square (side:{square.w})")
circle.toggle_anchor()
square.toggle_anchor()
I am open to other ways to do this, I just want to be able to use shapes as normal with the new functionality.
I am trying to avoid doing the following, as this involves heavy code duplication:
class AnchorCircle(Circle):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.anchor_shape = Circle(self.anchor_x + self.x,
self.anchor_y + self.y, 1)
def toggle_anchor(self):
...
class AnchorRectangle(Rectangle):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.anchor_shape = Circle(self.anchor_x + self.x,
self.anchor_y + self.y, 1)
def toggle_anchor(self):
...
class AnchorTriangle(Triangle):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.anchor_shape = Circle(self.anchor_x + self.x,
self.anchor_y + self.y, 1)
def toggle_anchor(self):
...
Edit1: correct typos and added more details.
Upvotes: 0
Views: 330
Reputation: 110301
What you are asking is one thing. What you describe as your needs is another thing.
What you really say you need can be resolved with multiple-inheitrance and no code redundancy - if you are only to review certain concepts.
Just create an AnchorShape class, which takes the new needed parameters, and keep using "super" as you are using, and then use multiple-inheirtance, with class declarations and empty bodies, to declare your specific classes:
class AnchorShape(Shape):
def __init__(self, *args, anchor_x=None, anchor_y=None, **kwargs):
super().__init__(*args, **kwargs)
self.anchor_shape = Circle(self.anchor_x + self.x,
self.anchor_y + self.y, 1)
def toggle_anchor(self):
...
class AnchorCircle(Circle, AnchorShape):
pass
class AnchorRectangle(Rectangle, AnchorShape):
pass
# and so on
Your question is about creating dynamic classes from objects (not from their classes) - that would be possible, but using a factory function (not a class), that would make a call to type
to create a class programmatically and then return an instance of that new class. But it really seems it is not your actual use case.
Upvotes: 1