0

I have some class inheritance.

class A1:
    def __init__(self, b):
        self.b = b

    def some_A_function():
        print("This is A1 function")

    # ... more A1 specific functions

class B(A1):
    def __init__(self, a, b):
        super().__init__(b)
        self.a = a

    # ... more B specific functions

class C(B):
    def __init__(self, a, b)
        super().__init__(a, b)
    # ... more C specific functions

if __name__ == "__main__":
    # Main instance
    a = 1
    b = 2
    C_obj = C(a, b)

Now, there is some introduction of class A2 as follows:

class A2:
    def __init__(self, b):
        self.b = b

    def some_A_function():
        print("This is A2 function")

Now, based on the value of a which is passed while creating an instance of class C, inheritance of class B is expected to change. For example, if a=1, B inherits class A1 else it inherits class A2.

I don't wish to change any code to class A1, A2, C and the main block as it has a huge amount of code around it which is practically very difficult to restructure it in any way. However, I can implement the logic based on the value of a to decide upon the inheritance of B by changing somethings in B or by calling some independent function.

I am new to factory functions in general. Most of the examples which I found in my search are implemented on the topmost level of hierarchy which assess the conditional and return the relevant implementation of the class (Something like if a==1, return C1 else C2. However, in my case, I don't know how to say to class C (in main function) to ask class B to inherit one of the two implementation of A (i.e. A1, A2) based on the value passed as the variable a.

CharcoalG
  • 185
  • 4
  • 12
  • Take a look at this question: https://stackoverflow.com/questions/9539052/how-to-dynamically-change-base-class-of-instances-at-runtime – Hugo Aboud Jan 18 '21 at 12:05
  • I already had a look at that one. The issue is, I can't carry on large restructuring of this hierarchy. Another thing is, the change has been made on the class at the topmost level of hierarchy in the accepted answer. In my case, the change in ```__bases__``` need to happen at the lowest level of hierarchy. I don't have a handler to change the bases attribute. – CharcoalG Jan 18 '21 at 12:43

1 Answers1

2

Not the cleanest solution I guess, but it can be achieved this way:

class A1:
    def __init__(self, b):
        self.b = b
    def some_A_function(self):
        print("This is A1 function", "b = " + str(self.b))

class A2:
    def __init__(self, b):
        self.b = b
    def some_A_function(self):
        print("This is A2 function", "b = " + str(self.b))

def get_class_B(base):
    class B(base):
        def __init__(self, a, b):
            super().__init__(b)
            self.a = a
    return B

def create_obj_C(a, b):
    if (a == 1): base = get_class_B(A1)
    elif (a == 2): base = get_class_B(A2)

    class C(base):
        def __init__(self, a, b):
            super().__init__(a, b)

    return C(a,b)

Then you'd have to create C through the auxiliary method create_obj_C.

create_obj_C(1, 2).some_A_function() # "This is A1 function, b = 2"
create_obj_C(2, 8).some_A_function() # "This is A2 function, b = 8"
Hugo Aboud
  • 443
  • 3
  • 10
  • This approach in my opinion is not scalable, i.e., if there are multiple inheritances from A->B->C->D->E, it'll be a bit difficult to carry the conditional variable to the lowest level without changing the pre-existing class definitions which is not always possible. However, your solution really helped me in getting to the right implementation for my case at the least. Thanks – CharcoalG Jan 18 '21 at 16:23