Search code examples
pythonclassinheritanceclass-structure

Python class interdependencies


I have a python class that serves as a baseclass for further subclasses. It contains a methods that should act on all subclass the same, e.g. I want to put it in the base class. The problem is, that this method should return a new instance of the subclass. But I since the baseclass is located before the definition of the subclass, I can not create a new instance of the subclass, as it is not known in the scope of the baseclass:

class Base:
  def __init__(self, value):
    self.value = value

  def convert_child_classes(self, newclass):
    newvalue = MakeUsableInNewclass(self.value)
    newattr = MakeUsableInNewclass(self.subclassattr)
    return newclass(newattr, newvalue)


class Child1(Base):
  def __init__(self, subclassattr, value)
    super(Child, self).__init__(value)
    self.subclassattr = subclassattr

  def MethodForSubClassAttr(self):
    ...do sth with self.subclassattr...


class Child2(Base):
  def __init__(self, subclassattr, value)
    super(Child, self).__init__(value)
    self.subclassattr = subclassattr

  def SomeOtherSubClassAttrMethod(self):
    ...do sth that is related to this class attr...

I if I have an instance of Child1 I want to be able to do some stuff with its data and then return an instance of the Child2 with the new values when calling convert_child_classes(Child2):

A = Child1('someattr', 5)
B = A.convert_child_classes(Child2)

now B should be an instance of Child2 with a value that was calculated form Child1. But since Base class does now know what Child1 or Child2 is, it can not initiate the new class.


Solution

  • I got your problem:
    1. Actually you're using Child in the super and it's wrong, as it should be the name of the class you're operating on, in this case Child1 or Child2.
    2. I'd add Base as an abstract class, to ensure it won't be instantiated (as I got from your question it's the case).
    3. since the method MakeUsableInNewClass is mandatory to be implemented, I'd add as an abstractmethod to ensure implementation on the Child ones.

    So the correct code would be:

    from abc import ABC, abstractmethod
    class Base(ABC):
        def __init__(self, value):
            self.value = value
    
        def convert_child_classes(self, newclass):
            newvalue, newattr = self.MakeUsableInNewclass()
            return newclass(newattr, newvalue)
    
        @abstractmethod
        def MakeUsableInNewclass(): pass
    
    class Child1(Base):
        def __init__(self, subclassattr, value):
            super(Child1, self).__init__(value)
            self.subclassattr = subclassattr
    
        def MakeUsableInNewclass(self):
            newvalue = self.value #do operations
            newattr = self.subclassattr #do operations
            return newvalue, newattr
    
    class Child2(Base):
        def __init__(self, subclassattr, value):
            super(Child2, self).__init__(value)
            self.subclassattr = subclassattr
    
        def MakeUsableInNewclass(self):
            newvalue = self.value #do operations
            newattr = self.subclassattr #do operations
            return newvalue, newattr