如何创建两个 child class 之一的新 object?

How to create new object of one of two child class?

我有class动物和两个Childclasses

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 type object 数组
class Engine:

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

我有函数 create_actor_child,输入 actor (Animal object)。这个函数应该创建新的 Animalsame child class。我正在使用 if - watching is Parent Bear - 生成 Bear,否则生成 Fish。但是如果我有 10 child 就很难了。我认为应该有创建 parent class 的新副本的解决方案。

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 中有简单的方法吗?还是我需要创建自己的方法?

从语义 POV 来看,继承描述了一种 "is a" 关系,所以(只要你的 child class 尊重 liskov 的替换原则)鱼或熊已经是动物.此外,创建 "new copy of parent class" 实际上会创建新的不同 objects,这当然不是您想要的。

更好的解决方案是保留 child classes 的寄存器(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 没有任何其他用途,您也可以直接使用 child class 本身(并删除注册表):

    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))

您可能还想查看 the abc module 一些更先进的功能 wrt/subclasses 等