【发布时间】:2018-02-16 12:22:36
【问题描述】:
实际的代码有很大的不同并且完全不同的主题,但我觉得这个小例子可能会更好,因为我的问题是理解复杂继承场景的关键概念(而不是我的特定领域)。
假设我们有一个基本的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-style) 来实现“能力”和其他东西。
例如,如果Orc 和Human 不仅要移动,还要能够跳跃,那么有这样的东西会很有趣:
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需要访问@ 987654339@.
对于此类问题,什么是干净的解决方案?
如果需要进一步的子类化怎么办?例如。我们可能有兴趣创建一个UndeadHuman,例如class UndeadHuman(Undead, Human)。由于线性化(Undead 按顺序排列),它应该具有Undead 的attack 行为,但它还需要来自Human 的CanJump。
【问题讨论】:
标签: python python-3.x inheritance abstract-class multiple-inheritance