微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

通过组合实现继承正确的方法

如何解决通过组合实现继承正确的方法

考虑一个例子(我已经尝试在不失去其本质的情况下尽可能地减少它),其中继承可能是合适的:

  • 我要介绍的是玩家在游戏中使用的物品。
  • 特定类型物品的两个示例是武器液体容器

如果我要使用继承来实现这个(在 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 举报,一经查实,本站将立刻删除。