Reputation: 41
I want to get instance of one of subclasses when trying get instance of a superclass (parent class) depending on arguments. For example, I have parent class(I'm using 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))
And subclass:
class YoungMan(Man):
def say_hello(self):
print("Hey, man! Wazap?")
If age of Man less 30, I want it become YoungMan:
John = Man('John', 25)
type(John) #<class '__main__.YoungMan'>
John.say_hello() #Hey, man! Wazap?
I tried solve it with Man.__new__()
:
class Man:
def __new__(cls, name, age):
if age < 30:
return YoungMan(name, age)
else:
return super(Man, cls).__new__()
...
But John.say_hello()
returns Hello! My name is John.
So Man
methods override YoungMan
methods. After I tried use metaclass for Man
:
class ManFactory(type):
def __call__(self, name, age):
if age < 30:
return YoungMan(name, age)
class Man(metaclass=ManFactory):
...
But it lached on ManFactory.__call__()
.
I understand that I can use a funtion John = get_Man(name, age)
which returns right class, but it isn't so handsome. My question is about how do it like this:
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.
Upvotes: 4
Views: 696
Reputation: 13498
Not sure if this is good practice but you could set 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?
The main problem with this method is that the YoungMan would still be constructed by Man.__init__()
so the classes would have to be compatible. Creating a function get_man()
is still the best solution.
Upvotes: 3