Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert superclass instance to subclass instance

  • I have an external library which I cannot touch. This library has a function, genA(), that returns the instance of class A.
  • In my side I define class B as a subclass of class A.
  • I want to use the instance of class B in my project, but the instance should be generated by genA().

Is there any standard and easy way to do this?


# I cannnot tweak these code

def genA():
    a = A
    return(a)

class A:
    def __init__():
        self.a = 1

# ---

# code in my side

class B(A):
    def __init__():
        self.b = 2


a = genA()
# like a copy-constructor, doesn't work
# b = B(a)

# I want to get this
b.a # => 1
b.b # => 2

Here is an equivalent c++ code:

#include <iostream>

// library side code
class A {
public:
  int a;
  // ... many members

  A() { a = 1; }
};

void fa(A a) {
  std::cout << a.a << std::endl;
}

A genA() { A a; return a; }

// ///
// my code

class B : public A {
public:
  int b;
  B() : A() { init(); }
  B(A& a) : A(a) { init(); }
  void init() { b = 2; }
};

void fb(B b) {
  std::cout << b.b << std::endl;
}


int main(void) {
  A a = genA();
  B b(a);

  fa(b); // => 1
  fb(b); // => 2
}
like image 450
kohske Avatar asked Mar 25 '15 23:03

kohske


People also ask

Can you convert a superclass to a subclass?

Yes. We can always convert ( Cast ) a superclass reference into a subclass reference.

Can you cast parent class to subclass?

As it was said before, you can't cast from superclass to subclass unless your object was instantiated from the subclass in the first place. However, there are workarounds.

Can a superclass access subclass variables?

Rule:A subclass inherits all of the member variables within its superclass that are accessible to that subclass (unless the member variable is hidden by the subclass). inherit those member variables declared with no access specifier as long as the subclass is in the same package as the superclass.


1 Answers

You shouldn't do it with __new__, but it works only with new-style classes:

class A(object):
    def __init__(self):
        self.a = 10

class B(A):
    def __new__(cls, a):
        a.__class__ = cls
        return a

    def __init__(self, a):
        self.b = 20

a = A()
b = B(a)

print type(b), b.a, b.b   # <class '__main__.B'> 10 20

But as I said, don't do that, you should probably use aggregation, not a subclassing in such cases. If you wish to make B so it will have same interface as A, you may write transparent proxy with __getattr__:

class B(object):
    def __init__(self, a):
        self.__a = a
        self.b = 20

    def __getattr__(self, attr):
        return getattr(self.__a, attr)

    def __setattr__(self, attr, val):
        if attr == '_B__a':
            object.__setattr__(self, attr, val)

        return setattr(self.__a, attr, val)
like image 149
myaut Avatar answered Nov 13 '22 08:11

myaut