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