So I’m writing some code and have recently come across the need to implement a few mixins. My question is, what is the proper way to design a mix-in? I’ll use the example code below to illustrate my exact query.
class Projectile(Movable, Rotatable, Bounded):
'''A projectile.'''
def __init__(self, bounds, position=(0, 0), heading=0.0):
Movable.__init__(self)
Rotatable.__init__(self, heading)
Bounded.__init__(self, bounds)
self.position = Vector(position)
def update(self, dt=1.0):
'''Update the state of the object.'''
scalar = self.velocity
heading = math.radians(self.heading)
direction = Vector([math.sin(heading), math.cos(heading)])
self.position += scalar * dt * direction
Bounded.update(self)
class Bounded(object):
'''A mix-in for bounded objects.'''
def __init__(self, bounds):
self.bounds = bounds
def update(self):
if not self.bounds.contains(self.rect):
while self.rect.top > self.bounds.top:
self.rect.centery += 1
while self.rect.bottom < self.bounds.bottom:
self.rect.centery += 1
while self.rect.left < self.bounds.left:
self.rect.centerx += 1
while self.rect.right > self.bounds.right:
self.rect.centerx -= 1
Basically, I’m wondering, are mix-ins sort of like Java interfaces where there is a sort of (in Python’s case implicit) contract that if one wishes to use the code one must define certain variables / functions (not unlike a framework), or is it more like the code I’ve written above, where each mix-in must be initialized explicitly?
You can have both behavior in Python. You can force the reimplementation by using Abstract Base Classes, or by raising NotImplementedError in virtual functions.
If init are important in parent’s classes, then you have to call them. As eryksun said, use the
superbuiltin function to call the parent’s initializers (this way, an initializer for a given class will only be called once).Conclusion: depends on what you have. In your case, you have to call init, and you should use
super.