首页 > 解决方案 > 从父类覆盖类方法而不影响下游类

问题描述

我想覆盖一个类中的继承方法(参见下面的__init__方法示例),同时让它的孩子仍然使用父母版本。

我知道我可以通过重新定义类__init__中的方法GrandChild或使用多重继承来实现所需的行为。但是,我的问题旨在通过仅对Child类及其__init__实现进行更改来实现相同目的。

(实际用例是明显更复杂的“遗留代码”,每个级别都有几个类。因此,这个问题的动机是在各个类中实现所需的行为,而不必触及其他类的实现或继承结构)

如果这是不可能的,我也希望对此做出解释。

class Parent:
    def __init__(self, a,b):
        self.a = a 
        self.b = b

    def __str__(self):
        return f"{self.a}, {self.b}"

class Child(Parent):
    # I would like to overwrite this method only for the Child Class and none of its children / downstream inhertiances
    def __init__(self, a):
        super().__init__(a, None)

class GrandChild(Child):
    # This Class should use the __init__ method of class Parent
    pass


parent = Parent("a","b")
child = Child("c")
# This throws a Type error right now since it calls the init method of class Child
grandchild = GrandChild("d", "e")

编辑:

如上所述,我知道我可以通过不同的方式实现所需的行为,例如更改类结构(如下所示)。然而,问题实际上更多的是关于 python 是否允许只对Child类进行更改。如果这在 python 中实际上是不可能的(不仅是不可取的),那么解释为什么比提供改变Child类实现之外的任何内容的替代实现更能回答我的问题。

class ChildCommonFunctionality(Parent):
    # Use this class for all common functionality originally provided by Child Class
    pass


class Child(ChildCommonFunctionality):
    # Use this class to override the init method
    def __init__(self, a):
        super().__init__(a, None)

class GrandChild(ChildCommonFunctionality):
    # This Class should use the __init__ method of class Parent
    pass

标签: pythoninheritance

解决方案


我找到了一种使用 _ init_subclass的方法,以确保所有子类都Child使用构造函数而不是受这篇文章启发Parent定义的构造函数:Child

class Parent:
    def __init__(self, a,b):
        self.a = a 
        self.b = b

    def __str__(self):
        return f"{self.a}, {self.b}"

class Child(Parent):
    # I would like to overwrite this method only for the Child Class and none of its children / downstream inhertiances
    def __init__(self, a):
        super().__init__(a, None)

    def __init_subclass__(cls):
        cls.__init__ = super().__init__

class GrandChild(Child):
    # This Class should use the __init__ method of class Parent
    pass

尽管这有点hacky,但它提供了实际绕过Childs init 方法的所需功能


推荐阅读