我开始为我正在编写的游戏定义我的实体类。但是,我想要重复使用大量代码。我想为不同的功能定义类,然后让类“拥有”这些类的一些功能。
例如:
class Collidable:
def handle_collision(other, incident_vector):
pass
def __init__(self, shape):
self.shape = shape
class Movable:
def update_position(self):
self.velocity += self.acceleration
self.position += self.velocity
def __init__(self, velocity, acceleration):
self.velocity, self.acceleration = velocity, acceleration
class Drawable:
def draw(self):
pass
def __init__(self, image):
self.image = image
class Controllable:
def key_down(self, key):
pass
def __init__(self):
pass
然后有一个Player
类,它是可碰撞的,可移动的,可绘制的,可控制的,Invisible Barrier
只有可碰撞的,Background
只是可画的,等等。我听说过连接多个类的许多不同方法(例如通过组合,(多个)继承,接口等),但我不知道哪种方式最适合和/或pythonic适用于这种情况。
super
将正确的参数传递给正确的init函数很困难。
修改
我正在使用python 3.2。
答案 0 :(得分:4)
Mixins是要走的路,但你不想在它们上面调用__init__
:
class CollidableMixin(object):
#...
def init_collidable(self, shape):
self.shape = shape
class MovableMixin(object):
#...
def init_movable(self, velocity, acceleration):
self.velocity, self.acceleration = velocity, acceleration
class DrawableMixin(object):
#...
def init_drawable(self, image):
self.image = image
我认为,Controllable
不需要单独的类,因为它只定义了继承类应具有的接口。虽然你在Java这样的静态类型语言中做了很多,但你不需要在Python中使用它。相反,您只需定义一个key_down
方法并完成它。这叫做鸭子打字。
在一个示例实现中,这将是这样的:
class Player(CollidableMixin, DrawableMixin, MovableMixin):
def __init__(self):
self.init_collidable(...)
self.init_drawable(...)
self.init_movable(...)
def key_down(self, key):
# ...
objects = []
objects.append(Player())
# ... add some more objects. Later we iterate through that collection,
# not knowing which of them is a player:
for o in objects:
try:
o.key_down(...)
except AttributeError:
pass
答案 1 :(得分:3)
这是使用super()
实现继承的简单方法。为此,您将始终需要使用关键字参数创建Player
(以及从您的***类继承的其他类)的实例。每个基类将从kwargs
中删除它使用的任何关键字参数,并将其余参数传递给mro中的下一个__init__()
,例如:
class Collidable(object):
def handle_collision(other, incident_vector):
pass
def __init__(self, shape, **kwargs):
self.shape = shape
super(Collidable, self).__init__(**kwargs)
class Movable(object):
def update_position(self):
self.velocity += self.acceleration
self.position += self.velocity
def __init__(self, velocity, acceleration, **kwargs):
self.velocity, self.acceleration = velocity, acceleration
super(Movable, self).__init__(**kwargs)
class Drawable(object):
def draw(self):
pass
def __init__(self, image, **kwargs):
self.image = image
super(Drawable, self).__init__(**kwargs)
class Controllable(object):
def key_down(self, key):
pass
def __init__(self, **kwargs):
super(Controllable, self).__init__(**kwargs)
然后你可以定义你的Player
类:
class Player(Collidable, Movable, Drawable, Controllable):
pass
并像这样使用它:
>>> p = Player(shape='circle', velocity=0.0, acceleration=1.0, image='player.png')
>>> p.shape
'circle'
>>> p.velocity
0.0
>>> p.acceleration
1.0
如果您需要Player
类的其他实例变量,您可以定义与其他类相似的__init__()
,例如:
class Player(Collidable, Movable, Drawable, Controllable):
def __init__(name, **kwargs):
self.name = name
super(Player, self).__init__(**kwargs)