Home > database >  Python Class Inheritance Prevent Parent Class from Calling Child Class Method
Python Class Inheritance Prevent Parent Class from Calling Child Class Method

Time:05-20

Hello I'd like to use a class method that requires multiple arguments as well as an attribute from the class' __init__().

However, because I have to make this call several times, I'd like to avoid providing multiple arguments to each call. Therefore, I thought to make a child class which supplies the arguments such as below. However, I don't want to override the parent method in the child class.

Here are the two classes with an example call:

class Parent:
    def __init__(self, parent_arg: dict) -> None:
        self.parent_arg = parent_arg

    def create_child(self, child_arg):
        return Child(child_arg, self.parent_arg)

    def method_a(self, method_arg: str, child_arg: str) -> dict:
        self.method_b(method_arg, child_arg)

    def method_b(self, method_arg: str, child_arg: str) -> str:
        print(f"{self.parent_arg}, {child_arg}, and {method_arg}")


class Child(Parent):
    def __init__(self, child_arg: str, parent_arg: dict) -> None:
        super().__init__(parent_arg)
        self.child_arg = child_arg

    def method_a(self, method_arg: str = None) -> dict:
        return super().method_a(method_arg, self.child_arg)

    def method_b(self, method_arg: str) -> str:
        return super().method_b(method_arg, self.child_arg)


if __name__ == "__main__":
    parent_instance = Parent(parent_arg="Parent Argument")
    child_instance = parent_instance.create_child(child_arg="Child Argument")
    child_instance.method_a(method_arg="Method Argument")

Again, I'd like to be able to call the same method names from Parent and Child instances. However, I'd like the computation to be done in the parent class methods. Thank you so so much for any and all help.

Here's one solution without inheritance, however, I'm curious if there's a more elegant solution.

class Child:
    def __init__(self, child_arg: str, parent_arg: dict) -> None:
        self.parent = Parent(parent_arg)
        self.child_arg = child_arg

    def method_a(self, method_arg: str = None) -> dict:
        return self.parent.method_a(method_arg, self.child_arg)

    def method_b(self, method_arg: str) -> str:
        return self.parent.method_b(method_arg, self.child_arg)

CodePudding user response:

I think the answer you're looking for is don't override method_b in the Child class.

You might be thinking that the execution "goes" to the parent when you call super(), and that's not right. You're "in" the same object the entire time (the self). If you simple omit method_b from your child definition, the value of child_instance.method_b will be the parent's definition.

Basically, only override these methods in the child if you have additional or different behavior you want to implement.


EDIT based on OP's comment

Take a look at this. It lets you assign attributes to objects as you create them, so you can re-use them without having to provide them on every method call. It implements Parent so that it is unaware of / not concerned with the Child. All the Child does is override the methods so it can make use of the additional child_arg param.

class Parent:
    def __init__(self, parent_arg: str) -> None:
        self.parent_arg = parent_arg

    def method_a(self, method_arg: str) -> None:
        self.method_b(method_arg)

    def method_b(self, method_arg: str) -> None:
        print(f"self.parent_arg: {self.parent_arg}")
        print(f"method_arg: {method_arg}")


class Child(Parent):
    def __init__(self, child_arg: str, parent_arg: str) -> None:
        super().__init__(parent_arg)
        self.child_arg = child_arg

    def method_a(self, method_arg: str) -> None:
        super().method_a(method_arg)

    def method_b(self, method_arg: str) -> None:
        print(f"self.parent_arg: {self.parent_arg}")
        print(f"self.child_arg: {self.child_arg}")
        print(f"method_arg: {method_arg}")


if __name__ == "__main__":

    parent_instance = Parent(parent_arg="Parent Argument")
    print("parent_instance calling a:")
    parent_instance.method_a("Method Argument")

    print("child_instance calling a:")
    child_instance = Child(
        child_arg="Child Argument",
        parent_arg="Parent Argument",
    )
    child_instance.method_a("Method Argument")

CodePudding user response:

If you don't want to call the child's method, call the method from a specific class directly instead of going through self.methodname.

    def method_a(self, method_arg: str, child_arg: str) -> dict:
        return Parent.method_b(self, method_arg, child_arg)
  • Related