调用父类时返回子类

时间:2018-07-14 06:22:01

标签: python python-3.x inheritance

当我尝试根据参数尝试获取超类(父类)的实例时,我想获取子类之一的实例。例如,我有一个父类(我正在使用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?")

如果男人的年龄小于30岁,我希望它成为年轻人:

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.,因此Man方法覆盖了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.

1 个答案:

答案 0 :(得分:3)

不确定这是否是一种好的做法,但您可以设置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()仍然是最佳解决方案。