Python 如何将相同的方法/属性添加到从公共类派生的一组子类中

Python 如何将相同的方法/属性添加到从公共类派生的一组子类中,python,class,subclass,Python,Class,Subclass,向派生自同一类的子类添加一组通用方法/属性的正确方法是什么 假设这些是我的课程,我需要一个基于动物的视频游戏(这只是一个例子,我不是在写游戏,但想法是一样的) 在游戏中的某一时刻,狗和鸭可以被武器化,它们需要有相同的方法:fire()、reload()和properties:ammocount 我认为将它们添加到Animal()类中是不正确的,因为在游戏的另一个完全不同的部分中需要它们 添加它们的正确方法是什么 更新 我想补充一点,预期的结果是 动物武器混合类 class BurtalDuck(

向派生自同一类的子类添加一组通用方法/属性的正确方法是什么

假设这些是我的课程,我需要一个基于动物的视频游戏(这只是一个例子,我不是在写游戏,但想法是一样的)

在游戏中的某一时刻,狗和鸭可以被武器化,它们需要有相同的方法:fire()、reload()和properties:ammocount

我认为将它们添加到Animal()类中是不正确的,因为在游戏的另一个完全不同的部分中需要它们

添加它们的正确方法是什么

更新 我想补充一点,预期的结果是 动物武器混合类

class BurtalDuck(Duck):
    fire(): #<- this is somehow added to Duck
        print "ratatatatat!"
class-BurtalDuck(Duck):

fire():#您可以利用python中的多重继承,如下所示:

class Weapon():
    def __init__(self):
        self.ammoCount = 0
    def fire():
        print "fire!"
    def reload():
        print "reloading!"

class Dog(Animal, Weapon):
    def __init(self, numlegs):
        Animal.__init__(numlegs)

    def bark(self):
        print "Arf!"
现在您可以执行以下操作:

dog = Dog(4)
dog.fire()
如果
只被认为是
动物
,而不是
动物
-
武器
-杂种,则使用
武器
的实例并将其作为组件分配给狗:

class Dog(Animal, Weapon):
    def __init(self, numlegs):
        Animal.__init__(numlegs)
        self.weapon = Weapon()

    def bark(self):
        print "Arf!"
然后你必须使用
狗.武器.火()。这可能不符合你的概念,狗实际上是一种武器,但它现在已经武器化了

如果您有一个dog实例,并且需要在运行中对其进行武器化,只需利用python的动态属性分配

class Dog(Animal):
    def __init(self, numlegs):
        Animal.__init__(numlegs)

    def bark(self):
        print "Arf!"
#some other code maybe
dog = Dog(4)
#more other code
dog.weapon = Weapon()
#even more code
dog.weapon.fire()
一般来说,我会说:

  • 如果你想
    成为武器,请使用继承
  • 如果您希望
    由一件(或多件)武器组成或拥有一件(或多件),请使用组件

    • 一种可能性:根本不要将它们添加到类中。创建一个“武器”类,该类包含有关武器如何工作的所有信息,并将该类的实例添加到可以成为武器的对象中


      当然,这意味着要重新思考一下您的体系结构,但这是一个值得思考的概念。这种想法通常被称为“基于组件”。并试着找到一些描述这个想法的博客帖子/演示文稿。

      通过写作来实现这一点

      class Weapon(object):
          def __init__(self, type):
              self.type = type
      
      class Dog(Animal):
          def __init(self, numlegs):
              Animal.__init__(numlegs)
              self.gun = Weapon("gun")
      
          def bark(self):
              print "Arf!"
      

      另一种方法是使用mixin:

      class Animal(object):
          def __init__(self, n):
              super(Animal,self).__init__()
              if isinstance(n, Animal):  # copy constructor
                  self.numlegs = n.numlegs
              else:
                  self.numlegs = n
          def do(self):
              pass
      
      class Dog(Animal):
          def do(self):
              print "Arf!"
      
      class Cat(Animal):
          def do(self):
              print "Torturing small animals is fun!"
      
      class Duck(Animal):
          def do(self):
              print "Wheee!"
      
      class Weapon(object):
          def __init__(self):
              super(Weapon,self).__init__()
              self.ammocount = 7
      
          def fire(self):
              if self.ammocount > 0:
                  print "Bang!"
                  self.ammocount -= 1
              else:
                  print "<click>"
      
          def reload(self):
              self.ammocount = 7
      
      class WeaponizedDog(Dog, Weapon): pass
      class WeaponizedCat(Cat, Weapon): pass
      class WeaponizedDuck(Duck, Weapon): pass
      
      max = Dog(4)                # max is a 4-legged dog
      max.do()                    # "Arf!"
      max = WeaponizedDog(max)    # If I put my hands in my pockets, I'd be carrying concealed deadly weapons...
      max.fire()                  # "Bang!"
      
      类动物(对象):
      定义初始化(self,n):
      超级(动物,自我)。\uuuuu初始
      如果是实例(n,动物):#复制构造函数
      self.numlegs=n.numlegs
      其他:
      self.numlegs=n
      def do(自我):
      通过
      犬类(动物):
      def do(自我):
      打印“Arf!”
      类别猫(动物):
      def do(自我):
      印刷“折磨小动物很有趣!”
      鸭类(动物):
      def do(自我):
      打印“Wheee!”
      类武器(对象):
      定义初始化(自):
      超级(武器,自我)。\uuuuuuu初始
      self.ammocount=7
      def火灾(自):
      如果self.ammocount>0:
      打印“砰!”
      self.ammocount-=1
      其他:
      打印“”
      def重新加载(自):
      self.ammocount=7
      职业武器装备日志(狗,武器):通过
      职业武器猫(猫,武器):通过
      职业武器化鸭子(鸭子,武器):传球
      马克斯=狗(4)#马克斯是一只四条腿的狗
      max.do()#“Arf!”
      马克斯=武器化(马克斯)#如果我把手放在口袋里,我会随身携带隐藏的致命武器。。。
      max.fire()#“砰!”
      
      不,这不是家庭作业,谢谢你问=)+1关于武器化鸭子的想法。我不知道混合体是什么,现在就查它们。@DSM(+1,如果你有参考资料的话),这就是为什么我去任何地方都会有我的猎鸭炭疽。好吧,再次编辑评论,我只想保留狗的a类动物亚类,并且只在我代码的另一部分将它们武器化(想象一下,在游戏的第2版中,我希望使用相同的类而不修改它们),我建议使用接口,但据我所知,python不支持:)也感谢您扩展了答案,阅读马克·希尔德雷思(MarkHildreth)关于继承与构成的问题的链接,一切都变得更加清晰。我很高兴我能提供帮助。:)使用组合而不是继承对于解耦尤其重要,并且经常用于实现。我肯定会仔细看一看。所谓“添加实例”,是指将其分配给类中的某个变量?这似乎不是很oop(但我是谁来说什么是oop?=)这可以归结为继承(您试图完成的)和组合(我的建议)之间的决定。他们有自己的优点和缺点,也有使用他们的人的偏见。以下问题提供了更多信息,可用于确定什么是好方法:
      class Animal(object):
          def __init__(self, n):
              super(Animal,self).__init__()
              if isinstance(n, Animal):  # copy constructor
                  self.numlegs = n.numlegs
              else:
                  self.numlegs = n
          def do(self):
              pass
      
      class Dog(Animal):
          def do(self):
              print "Arf!"
      
      class Cat(Animal):
          def do(self):
              print "Torturing small animals is fun!"
      
      class Duck(Animal):
          def do(self):
              print "Wheee!"
      
      class Weapon(object):
          def __init__(self):
              super(Weapon,self).__init__()
              self.ammocount = 7
      
          def fire(self):
              if self.ammocount > 0:
                  print "Bang!"
                  self.ammocount -= 1
              else:
                  print "<click>"
      
          def reload(self):
              self.ammocount = 7
      
      class WeaponizedDog(Dog, Weapon): pass
      class WeaponizedCat(Cat, Weapon): pass
      class WeaponizedDuck(Duck, Weapon): pass
      
      max = Dog(4)                # max is a 4-legged dog
      max.do()                    # "Arf!"
      max = WeaponizedDog(max)    # If I put my hands in my pockets, I'd be carrying concealed deadly weapons...
      max.fire()                  # "Bang!"