Как создать новый объект одного из двух дочерних классов? - PullRequest
0 голосов
/ 05 ноября 2018

У меня есть класс Животное и два Ребенок классы Рыба и Медведь

class Fish(Animal):

    def __init__(self, x, y, parent_engine):
        self.parent = parent_engine
        self.x = x
        self.y = y
        self.type = 2
        self.image = '?'
        self.life = 1


class Bear(Animal):

    def __init__(self, x, y, parent_engine):
        self.parent = parent_engine
        self.x = x
        self.y = y
        self.type = 3
        self.image = '?'
        self.life = 1

В коде у меня есть массив Животный тип объекты с именем Поле

class Engine:

    def __init__(self, size):
        self.field = []
        self.field_size = size

У меня есть функция create_actor_child с вводом actor (Объект Animal) . Эта функция должна создать новый Animal с того же дочернего класса . Я использую, если - смотреть это Родительский Медведь - порождать Медведя, иначе порождать Рыбу. Но если у меня будет 10 детей, это будет трудно. Я думаю, что должно быть решение для создания новой копии родительского класса.

def create_actors_child(self, actors):  # returns parents back

    sample = actors[0]

    x = sample.x
    y = sample.y

    for actor in actors:
        actor.go_back_event()

    if sample.type == 2:
        self.field.append(bp.Fish(x, y, self))
    else:
        self.field.append(bp.Bear(x, y, self))

Мне нужно что-то вроде self.field.append(parent_class(actor)).

Есть ли простой способ сделать это в Python или мне нужно создать свой собственный метод?

1 Ответ

0 голосов
/ 05 ноября 2018

из семантического POV, наследование описывает отношение "является", поэтому (если ваши дочерние классы уважают принцип замещения Лискова), рыба или медведь уже есть животное. Кроме того, создание «новой копии родительского класса» фактически создаст новые отдельные объекты, что, безусловно, не то, что вам нужно.

Лучшее решение - сохранить регистр (dict) дочерних классов (используя type в качестве ключа) и предоставить фабричную функцию или метод, то есть:

class Animal(object):
    # your code here


    # XXX : Q&D code, missing sanity checks and error handling
    __registry = {}

    @classmethod
    def register(cls, subcls): 
        cls.__registry[subcls.type] = subcls

    @classmethod
    def create(cls, type, x, y, engine):
        return cls.__registry[type](x, y, engine)



class Engine(object):

    def create_actors_child(self, actors):  # returns parents back

        sample = actors[0]

        x = sample.x
        y = sample.y

        for actor in actors:
            actor.go_back_event()

        self.field.append(Animal.create(sample.type, x, y, self))

Обратите внимание, что на данный момент, если у вас нет другого использования для Animal.type, вы также можете просто напрямую использовать дочерний класс (и избавиться от реестра):

    def create_actors_child(self, actors):  # returns parents back

        sample = actors[0]

        x = sample.x
        y = sample.y

        for actor in actors:
            actor.go_back_event()

        samplecls = type(sample)
        self.field.append(samplecls(x, y, self))

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

...