首页 > 解决方案 > 如何创建两个子类之一的新对象?

问题描述

我有动物课和两个儿童

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

在代码中,我有一个名为Field的Animal 类型对象数组

class Engine:

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

我有函数create_actor_child和输入actor (Animal object)。此函数应创建具有相同子类的新Animal。我正在使用 if - watch is Parent Bear - 生成熊,否则生成鱼。但是,如果我要生 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 中是否有一种简单的方法可以做到这一点,还是我需要创建自己的方法?

标签: pythonarraysclassparent-child

解决方案


从语义 POV 来看,继承描述了“是”关系,因此(只要您的子类尊重 liskov 的替换原则)鱼或熊已经是动物。此外,创建“父类的新副本”实际上会创建新的不同对象,这肯定不是您想要的。

更好的解决方案是保留子类的注册(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 模块,了解一些更进化的功能 wrt/子类等。


推荐阅读