简体   繁体   English

Python类继承防止父类调用子类方法

[英]Python Class Inheritance Prevent Parent Class from Calling Child Class Method

Hello I'd like to use a class method that requires multiple arguments as well as an attribute from the class' __init__() .您好,我想使用一个需要多个参数以及来自类的属性的类方法__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.同样,我希望能够从ParentChild实例调用相同的方法名称。 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)

I think the answer you're looking for is don't override method_b in the Child class .我认为您正在寻找的答案是不要覆盖Child类中的method_b

You might be thinking that the execution "goes" to the parent when you call super() , and that's not right.当您调用super()时,您可能会认为执行“转到”父级,这是不对的。 You're "in" the same object the entire time (the self ).你一直“在”同一个对象( self )。 If you simple omit method_b from your child definition, the value of child_instance.method_b will be the parent's definition.如果您从子定义中简单地省略method_b ,则child_instance.method_b的值将是父定义。

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根据 OP 的评论进行编辑

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 .它实现了Parent ,因此它不知道/不关心Child All the Child does is override the methods so it can make use of the additional child_arg param. Child所做的只是覆盖这些方法,以便它可以使用额外的child_arg参数。

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")

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 .如果您不想调用孩子的方法,请直接从特定类调用方法,而不是通过self.methodname

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM