Когда класс гарантирует подкласс?

Например, я пытаюсь создать класс противника для простой игры. Каждый враг, который появляется, имеет тип, который влияет на его характеристики, которые являются полями в классе врага.

class Enemy:
    #Base Stats for all enemies
    name = "foo"
    current_health = 4
    max_health = 4
    attack = 0
    defense = 0
    armor = 0
    initiative = 0
    initMod = 0
    alive = True

Должен ли каждый тип быть подклассом врага, как это..

class goblin(Enemy):
    name = goblin;
    current_health = 8
    max_health = 8
    attack = 3
    defense = 2
    armor = 0

    def attack(){
        //goblin-specific attack
    }

Но этот метод означает, что мне нужно будет создать класс для каждого отдельного типа (а это будет более 80 классов), или есть лучший способ сделать это? Этот враг будет рандомизирован, поэтому я подумал, что типы можно также поместить в словарь, в котором имена типов используются в качестве ключевых слов. Хотя я не совсем уверен, как я мог это реализовать.

3 ответа

Решение

Если вы хотите пройти путь словаря, вы можете сделать что-то вроде этого с кортежем, возвращаемым ключом:

enemy_types = {"goblin": ("goblin", 8, 8, 3, 2, 0, goblin_attack)}

def goblin_attack(enemy):
    do_stuff()

Хотя вы можете использовать named_tuple

/questions/35849374/chto-takoe-imenovannyie-kortezhi-v-python/35849383#35849383

чтобы убедиться, что вы не перепутали поля в кортеже

Гоблин, вероятно, должен быть примером врага. Однако в вашем примере вы добавили метод attack, Я бы сказал, что лучший способ сделать это так:

class Enemy:
   #Base Stats for all enemies
  def __init__ (self, **kwargs):
   self.name = "foo"
   self.current_health = 4
   self.max_health = 4
   self.attack = 0
   self.defense = 0
   self.armor = 0
   self.initiative = 0
   self.initMod = 0
   self.alive = True
   # Use this to specify any other parameters you may need
   for key in kwargs:
       exec ("self.%s = %s" % (key, kwargs[key])

Теперь вы можете создать экземпляр Enemy называется гоблин.

Чтобы ответить на ваш первоначальный вопрос о том, когда использовать подкласс, я бы сказал, что использование подклассов - это здорово, но в вашем случае это может усложнить ситуацию. Поскольку у вас есть только один метод в вашем подклассе, вы можете легко создать модуль, а затем иметь аргумент в __init__ который определяет attack функция. Это упростит ваш код еще больше.

Примечание: если вы собираетесь использовать подклассы, убедитесь, что в __init__ вашего подкласса вы называете __init__ вашего базового класса с super(),

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

Если вам нужны различные действия и тому подобное, возможно, вы могли бы сгруппировать свои 80 типов в различные коллекции, которые затем имели бы общие атрибуты (например, FlyingEnemy, UndeadEnemy, так далее). Тогда они станут вашими подклассами.

Другие вопросы по тегам