首页 > 解决方案 > 调用父类时返回子类

问题描述

在尝试根据参数获取超类(父类)的实例时,我想获取其中一个子类的实例。例如,我有父类(我正在使用 python3):

class Man:

    def __init__(self, name, age):
        self.name = name
        self.age = age

    def say_hello(self):
        print("Hello! My name is {}.".format(self.name))

和子类:

class YoungMan(Man):

    def say_hello(self):
        print("Hey, man! Wazap?")

如果 Man 的年龄小于 30,我希望它成为 YoungMan:

John = Man('John', 25)
type(John) #<class '__main__.YoungMan'>
John.say_hello() #Hey, man! Wazap?

我尝试用以下方法解决它Man.__new__()

class Man:

    def __new__(cls, name, age):
        if age < 30:
            return YoungMan(name, age)
        else:
            return super(Man, cls).__new__()
    ...

John.say_hello()返回Hello! My name is John.SoMan方法会覆盖YoungMan方法。在我尝试使用元类之后Man

class ManFactory(type):

    def __call__(self, name, age):
        if age < 30:
            return YoungMan(name, age)

class Man(metaclass=ManFactory):
    ...

但它卡住了ManFactory.__call__()

我知道我可以使用一个John = get_Man(name, age)返回正确类的函数,但它并不那么漂亮。我的问题是如何做到这一点:

John = Man('John', 25)
type(John) #<class '__main__.YoungMan'>
John.say_hello() #Hey, man! Wazap?

Brad = Man('Brad', 54)
type(Brad) #<class '__main__.Man'>
Brad.say_hello() #Hello! My name is Brad.

标签: pythonpython-3.xinheritance

解决方案


不确定这是否是好的做法,但您可以设置self.__class__

class Man:

    def __init__(self, name, age):
        if age < 30: self.__class__ = YoungMan
        self.name = name
        self.age = age

    def say_hello(self):
        print("Hello! My name is {}.".format(self.name))


class YoungMan(Man):

    def say_hello(self):
        print("Hey, man! Wazap?")


a = Man("Brad", 15)
print(type(a))
>>><class '__main__.YoungMan'>
a.say_hello()
>>>Hey, man! Wazap?

这种方法的主要问题是 YoungMan 仍然是由构造的,Man.__init__()所以类必须兼容。创建一个函数get_man()仍然是最好的解决方案。


推荐阅读