2016-08-09 3 views
0

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

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 + классов), или есть лучший способ сделать это? Это враг собирается быть рандомизированы, так что я думал о типы можно также положить в словарь который использует имена типов в качестве ключевых слов. Хотя я не совсем уверен, как это реализовать.

+0

С этим множеством потенциальных подклассов вы, вероятно, не очень хорошо моделируете проблему. С одной стороны, это звучит так, будто вы вводите в заблуждение «is-a» с «has-a» отношениями и, возможно, с классами и экземплярами классов. Большинство перечисленных атрибутов, вероятно, будут инициализированы в конструкторе класса или подкласса ('__init __()'). Кроме того, все определения методов класса автоматически получают первый аргумент, обычно называемый 'self', который является экземпляром класса. Поэтому вам нужно будет иметь 'def attack (self):'. Кроме того, Python не использует '{' и '}' скобки таким образом. – martineau

ответ

0

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

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

def goblin_attack(enemy): 
    do_stuff() 

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

https://stackoverflow.com/a/13700868/2489837

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

+0

Я думаю, что это маршрут, который я собираюсь преуспеть. Чтобы прояснить это, каждый враг следует тем же правилам боя. Они могут атаковать или защищаться, но то, что они делают во время атаки, может варьироваться в зависимости от их особых способностей. Должен ли я создать отдельную функцию для каждого другого типа врага в моем словаре? И будут ли эти функции находиться в моем файле класса врага? – Czurch

+0

Это должно быть до вас. Все мое решение - это возврат указателя функции для любой функции. В зависимости от того, каковы их специальные атаки (т. Е. Вы можете просто передать параметр для того, сколько урона он имеет, или у него есть более специальные материалы, связанные с ним), вам может понадобиться уникальная функция для каждого из них. В любом случае вы все равно можете использовать этот словарь и вернуть кортеж/объект или что у вас есть. –

0

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

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

+0

Мне очень нравится эта идея, может ли она также работать с идеей user2489837, чтобы использовать словарь для разных врагов? Таким образом, у меня мог бы быть список FlyingEnemies или UndeadEnemies. – Czurch

0

Гоблин, вероятно, должен быть примером Врага. Однако в вашем примере вы добавили метод с именем 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__ ваших BaseClass с super().

+0

Весь цикл 'for' в конце может быть заменен на' self .__ dict __. Update (kwargs) '. Как правило, нужно избегать использования 'exec', когда это возможно, и обычно это так. Ваш отступ также несовместим (а не 4 пробела, см. [PEP 8 - Руководство по стилю для кода Python] (https://www.python.org/dev/peps/pep-0008/)). – martineau

+0

Прошу прощения за недостаток знаний о словарях, но я думаю, что понимаю, что вы здесь делаете. Поэтому я бы определил словарь со всеми разными типами врагов. Когда я создаю новый экземпляр врага, мне нужно ввести ключ для одного из этих врагов. Этот ключ используется для ссылки на тип словаря, который инициализирует поля врага значениями, указанными в словаре. p.s. Спасибо, что нашли время ответить – Czurch