Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you cast an instance to a derived class?

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.

like image 293
Chris Lieb Avatar asked Jul 13 '09 15:07

Chris Lieb


People also ask

Can you cast from base class to derived?

When we create an instance of a base class, its data members are allocated in memory, but of course data members of inherited classes are not allocated. So, downcasting from a base to a derived class is not possible because data members of the inherited class are not allocated.

How do you assign a base class to a derived class?

You could write a constructor in the derived class taking a base class object as parameter, copying the values. In that case you would copy the base object and get a fully functional derived class object with default values for derived members.

Can you cast a base class to a derived class in C++?

C++ Explicit type conversions Base to derived conversion Likewise, a reference to base class can be converted to a reference to derived class using static_cast . If the source type is polymorphic, dynamic_cast can be used to perform a base to derived conversion.


1 Answers

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.

like image 88
Laurence Gonsalves Avatar answered Sep 27 '22 22:09

Laurence Gonsalves