如何解决通过组合实现继承正确的方法
考虑一个例子(我已经尝试在不失去其本质的情况下尽可能地减少它),其中继承可能是合适的:
- 我要介绍的是玩家在游戏中使用的物品。
- 特定类型物品的两个示例是武器和液体容器
如果我要使用继承来实现这个(在 Python 中),我会做这样的事情:
class Item:
def __init__(self,name):
self.name = name
def name(self):
return self.name
class Weapon(Item):
def __init__(self,name,damage):
super().__init__(name)
self.damage = damage
def hit():
return self.damage
class LiquidContainer(Item):
def __init__(self,drinks,max_drinks):
super().__init__(name)
self.drinks = drinks
self.max_drinks = drinks
def isEmpty():
return self.drinks == 0
def isFull():
return self.drinks == self.max_drinks
# driver code
letter = Item("mail")
sword = Weapon("longsword",8)
flask = LiquidContainer("canteen",5,5)
但现在假设我的老板告诉我始终使用组合而不是继承。我的直觉是做以下事情。
class Item:
def __init__(self,name):
self.name = name
def name(self):
return self.name
class Weapon:
def __init__(self,damage):
self.item = Item(name)
self.damage = damage
def name(self):
return self.item.name()
def hit():
return self.damage
class LiquidContainer:
def __init__(self,max_drinks):
self.item = Item(name)
self.drinks = drinks
self.max_drinks = max_drinks
def name(self):
return self.item.name()
def isEmpty():
return self.drinks == 0
def isFull():
return self.drinks == self.max_drinks
# driver code
letter = Item("mail")
sword = Weapon("longsword",5)
这感觉很自然,因为它类似于数学的完成方式。例如,一个拓扑空间是一个有序对(X,T),其中
- X 是一个集合,并且
- T 是满足某些条件的 X 子集的集合(这里不重要)。
但我发现这种方法没有吸引力,因为对于引入的每一种新的特定类型的物品(灯笼、盔甲、食堂、食物、工具等),我都必须再次手动解除物品的所有行为类(就像我对 name 函数所做的那样)。在基类有很多功能的情况下,这感觉像是一种反模式。
我的问题:
以相反的顺序组合对象是否是一种可行的方法,Item 类实际上是外部类?这是我的意思:
class Item:
def __init__(self,special=None):
self.name = name
self.special = special
def name(self):
return self.name
def isWeapon(self):
return type(self.special) == Weapon
def isLiquidContainer(self):
return type(self.special) == LiquidContainer
def hit(self):
if self.isWeapon():
return self.special.hit()
def isEmpty(self):
if self.isLiquidContainer():
return self.special.isEmpty()
def isFull(self):
if self.isLiquidContainer():
return self.special.isFull()
class Weapon:
def __init__(self,damage):
self.damage = damage
def hit(self):
return self.damage
class LiquidContainer:
def __init__(self,max_drinks):
self.drinks = drinks
self.max_drinks = max_drinks
def is_empty(self):
return self.drinks == 0
def is_full(self):
return self.drinks == self.max_drinks
# driver code
letter = Item("mail")
sword = Item("longsword",Weapon(8))
flask = Item("canteen",LiquidContainer(5,5))
现在在这个方法中,来自 Weapon、LiquidContainer 和任何其他被引入的 Item 类型的行为将被提升到 Item 类,而不是相反。
但这对我来说似乎更可取——我不必一遍又一遍地编写相同的函数来将 Item 类的行为提升到每种新类型的项目。
其他几个优点:
- 以这种方式创建的每个 Weapon 或 LiquidContainer 实际上都是 Item 类的实例。因此,在某种意义上,它是比之前的方法更真实的继承。
- 这是一个晦涩的功能,但这实际上是我最初偶然发现这种方法的原因:可以在知道它们将是什么类型之前创建项目。如果我只能访问 Item 的名称,我可以继续创建它,然后在获得更多信息后,我可以在准备好时通过指定 Item.special 字段来完成组合。
这是一种更喜欢组合而不是继承的有效方式,还是我会为自己设置问题?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。