How do you cast an instance to a derived class?
inheritance, oop, python
Solution
Rather than "casting", I think you really want to create an `UnapprovedUser` rather than a `User` when invoking `UnapprovedUser.get()`. To do that:
Change `User.get` to actually use the `cls` argument that's passed-in:
@classmethod
def get(cls, uid):
ldap_data = LdapUtil.get(uid + ',' + self.base_dn)
return cls._from_ldap(ldap_data)
You'll need to do something similar in `_from_ldap`. You didn't list the code for `_from_ldap`, but I assume that at some point it does something like:
result = User(... blah ...)
You want to replace this with:
result = cls(... blah ...)
Remember: in Python a class object is a callable that constructs instances of that class. So you can use the `cls` parameter of a classmethod to construct instances of the class used to call the classmethod.
Problem
I am trying to use a little inheritance in a Python program I am working on. I have a base class, User, which implements all of the functionality of a user. I am adding the concept of an unapproved user, which is just like a user, with the addition of a single method. The User class has some methods that return a User object. This will not work when I subclass, since I will end up having an UnapprovedUser return a User, preventing me from calling this method, among other things. ``` class User(object): base_dn = 'ou=Users,dc=example,dc=org' @classmethod def get(cls, uid): ldap_data = LdapUtil.get(uid + ',' + self.base_dn) return User._from_ldap(ldap_data) class UnapprovedUser(User): base_dn = 'ou=UnapprovedUsers,dc=example,dc=org' def approve(self): new_dn = '' # the new DN LdapUtil.move(self.dn, new_dn) ``` The `get()` and `_from_ldap()` methods are the same for both classes, though the `get()` method in UnapprovedUser needs to return an UnapprovedUser object, not a User. How can I cast one of the instances of User that I get from `User.get()` into an UnapprovedUser? I want to do something like: ``` class UnapprovedUser(User): # continued from before @classmethod def get(cls, uid): user = super(UnapprovedUser, cls).get(uid) return (UnapprovedUser) user # invalid syntax ``` so that I can wrap the method from the parent and simply cast the returned value to the correct class. Then again, doing it that way could lead to the parent using their value for `self.base_dn`, which would break everything.