实际代码与完全不同的主题,但我认为这个小例子可能更好,因为我的问题是理解复杂继承场景的关键概念,而不是我的特定领域。
让我们考虑一个基本的Entity类:
这是一个其他具体实体继承的基类,并且
现在我们可以实现一些实体:
这很好用。但是,我正在努力寻找一个好的解决方案(DRY风格),用于实现“能力”等其他内容。 例如,如果“兽人”和“人类”不仅应该移动,而且还应该能够跳跃,那么有这样的东西会很有趣:
这里有两个问题。(1)我们需要在
如果需要进一步的子类化怎么办?例如,我们可能有兴趣创建一个
让我们考虑一个基本的Entity类:
from enum import Enum
from abc import abstractmethod
class Condition(Enum):
ALIVE = 1
DEAD = 2
UNDEAD = 3
class Entity(object):
def __init__(self):
self.condition = Condition.ALIVE
self.position = 0
self.hitpoints = 100
def move(self):
self.position += 1
def changeHitpoints(self, amount):
self.hitpoints += amount
@abstractmethod
def attack(self, otherEntity):
pass
这是一个其他具体实体继承的基类,并且
attack()
必须是抽象的,因为每个实体都应该实现自己的攻击方法风格。现在我们可以实现一些实体:
class Orc(Entity):
def __init__(self):
super().__init__()
self.hitpoints = 150
self.damage = 10
def attack(self, otherEntity : Entity):
otherEntity.changeHitpoints(-self.damage)
class Human(Entity):
def __init__(self):
super().__init__()
self.damage = 8
def attack(self, otherEntity : Entity):
otherEntity.changeHitpoints(-self.damage)
class Undead(Entity):
def __init__(self):
super().__init__()
self.condition = Condition.UNDEAD
self.damage = 5
def attack(self, otherEntity : Entity):
# harm enemy
otherEntity.changeHitpoints(-self.damage)
# heal yourself
self.changeHitpoints(1)
这很好用。但是,我正在努力寻找一个好的解决方案(DRY风格),用于实现“能力”等其他内容。 例如,如果“兽人”和“人类”不仅应该移动,而且还应该能够跳跃,那么有这样的东西会很有趣:
class CanJump(Entity):
def jump(self):
self.position += 2
class Orc(Entity, CanJump):
(...)
class Human(Entity, CanJump):
(...)
这里有两个问题。(1)我们需要在
CanJump
中访问self.position
,因此我们必须继承Entity
?但如果这样做,我们就必须在CanJump
类中实现抽象方法attack()
。这是没有意义的,因为CanJump
应该只给予实体一种新的移动方式。(2)将来,我们可能想要实现例如一个修饰器,在执行move()
、attack()
等之前检查实体的条件是否为Condition.DEAD
。这也意味着CanJump
需要访问self.condition
。
针对这种类型的问题,有什么简洁的解决方案吗?如果需要进一步的子类化怎么办?例如,我们可能有兴趣创建一个
UndeadHuman
,像这样:class UndeadHuman(Undead, Human)
。由于线性化(Undead
首先按顺序),它应该具有Undead
的attack
行为,但它还需要Human
的CanJump
。
CanJump
?因为某些情况下可能会不小心这么做,然后self.position += 2
就会出现未解决的引用错误。此外,我想知道我们是否可以以某种方式对属性进行类型提示? - daniel451