Convert A Baseclass Object Into A Subclass Object Idiomatically?
There is a base class Base and a subclass Special. class Base(object): def __init__(self, name): self.name = name def greet(self): return 'Hello %s' % self.
Solution 1:
You can achieve this by defining an alternate constructor and reassigning the instance's __class__
attribute.
classBase(object):def__init__(self, name):
self.name = name
defgreet(self):
return'Hello %s' % self.name
@classmethoddefalt_constructor(cls, *args, **kwargs):
obj = cls(*args, **kwargs)
obj.__class__ = Special
return obj
classSpecial(Base):def__init__(self, name):
super(Special, self).__init__(name)
defrhyme(self):
return'Hi %s! How are you? Fine, thanks. What about you?' % self.name
>>> s = Base.alt_constructor("test")
>>> print s.rhyme()
Hi test! How are you? Fine, thanks. What about you?
EDIT:
Moved the constructor from Special
to Base
.
If you can't modify the Base
class you can add a classmethod to Special
that will change the class of any object passed to it.
classBase(object):
def__init__(self, name):
self.name = name
defgreet(self):
return'Hello %s' % self.name
classSpecial(Base):
def__init__(self, name):
super(Special, self).__init__(name)
defrhyme(self):
return'Hi %s! How are you? Fine, thanks. What about you?' % self.name
@classmethoddefconvert_to_special(cls, obj):
obj.__class__ = Special
>>> b = Base("test")
>>> printtype(b)
<class'__main__.Base'>
>>> Special.convert_to_special(b)
>>> printtype(b)
<class'__main__.Special'>
A more all purpose solution would be to create a mixin that can be added to any class.
classConverterMixin(object):
@classmethoddefconvert_to_class(cls, obj):
obj.__class__ = cls
classSpecial(ConverterMixin, Base):
def__init__(self, name):
super(Special, self).__init__(name)
defrhyme(self):
return'Hi %s! How are you? Fine, thanks. What about you?' % self.name
>>> b = Base("test")
>>> printtype(b)
<class'__main__.Base'>
>>> Special.convert_to_class(b)
>>> printtype(b)
<class'__main__.Special'>
Solution 2:
actually you can, but I don't think you should. instead of typecasting python has duck-typing to solve this kind of situation.
anyway, here's the code:
>>>base = Base("I'm a base!")>>>hasattr(base, 'rhyme')
False
>>>base.__class__ = Special>>>hasattr(base, 'rhyme')
True
>>>base.rhyme()
"Hi I'm a base!! How are you? Fine, thanks. What about you?"
Post a Comment for "Convert A Baseclass Object Into A Subclass Object Idiomatically?"