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

时间:2012-06-18 15:59:54

标签: python class subclass

为从同一个类派生的子类添加一组通用方法/属性的正确方法是什么?

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

class Animal():
    def __init(self, numlegs):
        self.numlegs = numlegs

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

    def bark(self):
        print "Arf!"

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

    def playwithmouse(self):
        print "It's fun!"

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

    def fly(self):
        print "Weee!"

在游戏中的某个时刻,Dog and Duck可以被武器化,并且它们需要具有相同的方法:fire(),reload()和属性:ammocount。

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

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

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

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

我从答案中得到的结果是,如果我需要整套“武器/ ammos”,我可以使用多重分类,否则构图就可以了。

4 个答案:

答案 0 :(得分:4)

您可以在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()

如果Dog <{1}},而不是Animal - {{1} } -hybrid,然后使用Animal的实例并将其作为组件分配给狗:

Weapon

然后你必须使用Weapon。这可能不符合class Dog(Animal, Weapon): def __init(self, numlegs): Animal.__init__(numlegs) self.weapon = Weapon() def bark(self): print "Arf!" 实际上 武器的概念,但它现在被武器化了。 :)

如果您有一个狗实例,并且您需要它即时进行武器化,只需利用python的动态属性分配

dog.weapon.fire()

一般来说,我会说:

  • 如果您希望Dogclass 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() 是武器,请使用继承。
  • 如果您希望DogDuck 包含拥有一个(或多个)武器,请使用组件。

答案 1 :(得分:3)

使用构图

执行此操作
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!"

答案 2 :(得分:2)

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

当然,这意味着对您的架构进行一点反思,但这是一个值得思考的好概念。这个想法通常以“基于组件”为名。 Google for "component-based game objects"并试着找一些描述这个想法的博客文章/演示文稿。

答案 3 :(得分:0)

使用mixins的另一种方法:

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!"