2016-01-15 2 views
0

Я просто пытаюсь собрать простой пример RPG, чтобы узнать ООП в Python.Python Multiple Inheritance (пример RPG)

Я создал базовый класс CharRace (объект). Затем я создал из этого два производных класса: Elf (CharRace) и Dwarf (CharRace). Кроме того, у меня есть второй базовый класс CharClass (объект) с двумя производными классами: Wizard (CharClass) и Warrior (CharClass).

Что бы я хотел сделать, это создать новый класс под названием NewChar, чтобы я мог передавать имя, расы и класс, и он создаст соответствующий объект, который наследует все свойства обоих расы и класса.

Например, я хочу, чтобы создать класс экземпляр NewChar с чем-то вроде этого: player1 = NewChar ("Боб", Эльф, Мастер) Player2 = NewChar ("Фил", Гном, Воин)

Я уверен, что есть разумный/правильный/масштабируемый способ сделать это, или, возможно, мои классы должны быть организованы по-разному, но мне трудно найти его. Любая помощь или совет оцениваются!

class CharRace(object): 
    'race for all characters' 
    health = 0 
    mana = 0 
    race = "" 
    name = "" 
    def __init__(self, health, mana, race, name): 
     self.health = health 
     self.mana = mana 
     self.race = race 
     self.name = name 
     print ("self = ",self) 
    def decreaseHealth (self, amount): 
     self.health = self.health - amount 
     print ("Decreased health to: ", self.health) 
     if (self.health) <= 0: 
      print (self.name, "has died!!!") 
    def increaseHealth (self, amount): 
     self.health = self.health + amount 
     print ("Increased health to: ", self.health) 
    def printStats(self): 
     print() 
     print("Stats for",self.name) 
     print (" Race =",self.race) 
     print (" Health =",self.health) 
     print (" Mana =",self.mana) 
     CharClass.printStats(self) 
    def __str__(self): 
     return (self.name) 

class CharClass(object): 
    'class for all characters' 
    weapon = "" 
    armor = 0 
    def __init__(self, weapon, armor, classname): 
     self.weapon = weapon 
     self.armor = armor 
     self.classname = classname 
     print ("self = ",self) 
    def printStats(self): 
     print (" Weapon =",self.weapon) 
     print (" Armor =",self.armor) 

# Character Classes 
class Warrior(CharClass): 
    'warrior class' 
    weapon = "Sword" 
    armor = 200 
    classname = "Warrior" 
    def __init__(self): 
     CharClass.__init__(self, self.weapon, self.armor, self.classname) 

class Wizard(CharClass): 
    'wizard class' 
    weapon = "Wand" 
    armor = 100 
    classname = "Wizard" 
    def __init__(self): 
     CharClass.__init__(self, self.weapon, self.armor, self.classname) 

# Character Races 
class Elf(CharRace): 
    'Elf subclass' 
    health = 100 
    mana = 200 
    race = "Elf" 
    def __init__(self, name): 
     CharRace.__init__(self, self.health, self.mana, self.race, name) 

class Dwarf(CharRace): 
    'Dwarf subclass' 
    health = 200 
    mana = 100 
    race = "Dwarf" 
    def __init__(self, name): 
     CharRace.__init__(self, self.health, self.mana, self.race, name) 


# This is not an efficient or scalable way to do this.... 
class ElfWarrior(Elf,Warrior): 
    'New character creation' 
    def __init__(self, name): 
     Elf.__init__(self, name) 
     Warrior.__init__(self) 

class ElfWizard(Elf,Wizard): 
    'New character creation' 
    def __init__(self, name): 
     Elf.__init__(self, name) 
     Wizard.__init__(self) 

class DwarfWarrior(Dwarf,Warrior): 
    'New character creation' 
    def __init__(self, name): 
     Dwarf.__init__(self, name) 
     Warrior.__init__(self) 

class DwarfWizard(Dwarf,Wizard): 
    'New character creation' 
    def __init__(self, name): 
     Dwarf.__init__(self, name) 
     Wizard.__init__(self) 
+3

Возможно, вы захотите найти композицию вместо использования наследования. В качестве альтернативы, я думаю, вы могли бы использовать фабрику классов. – M4rtini

+0

Вы можете создавать новые произвольные типы с произвольными базовыми классами, используя ['type()'] (https://docs.python.org/3/library/functions.html?highlight=type#type) (например, 'type (' NewChar ', (Elf, Warrior, ...), {}) '). Однако я согласен с @ M4rtini: композиция лучше подходит для такого рода вещей (особенно когда вещи начинают усложняться). –

ответ

0

То, что я хотел бы быть в состоянии сделать, это создать новый класс NewChar, что я могу передать имя, расу и класс, и это создаст соответствующий объект, наследующий все свойства как расы, так и класса.

Если вы действительно хотите использовать этот подход, вы можете попробовать что-то вроде этого:

def create_character(race, class, name): 
    type_name = race.__name__ + class.__name__ 
    return type(type_name, (race, class), {'name'=name} 

Here хорошее обсуждение функции типа и метаклассов, которые можно использовать для точной настройки это еще больше.

Тем не менее, это не самый лучший подход. Предпочитают композицию для наследования. Что делать, если ваш персонаж меняет класс, или вы хотите использовать двойной класс?

Вы можете попробовать что-то вроде этого, вместо:

class Character(object): 

    def __init__(name, race, class): 
     self.name = name 
     self.race = race.race 
     #etc 

    def increase_health(amount): 
     self.race.increase_health(amount) 

Отъезд книга Design Patterns: Элементы повторно используемого объектно-ориентированного программного обеспечения или Patterns Head First Design, чтобы узнать больше.

+0

Спасибо за совет! Сейчас я пытаюсь заставить композицию работать. Два вопроса: 1) Я думаю, что все еще запутанный в классе символов, который вы определили выше, почему мне нужно назначить все атрибуты из базовых классов? Разве это не значит, что функции __init__? 2) Ни один из методов базового класса не работает в классе символов (например, y = Character (Elf, Wizard, «Bob»), y.increaseHealth (10). Разве это не точка базового класса, что любые подклассы наследовать все их методы? – Rhinopotamus

+0

1.) Я сделал глупую опечатку. Вы правы, вам не нужно переназначать все атрибуты. 2). Сейчас это композиция, а не наследование, поэтому вы теряете немного удобства. Вам нужно будет определить функции для вызова функций члена. См. Править для пояснения. – JETM