简体   繁体   English

为什么要从继承的类调用基类构造函数

[英]Why call a base class constructor from inherited class

I have been trying to understand this use case, where we often call a base class constructor from the inherited class, is the sole purpose of doing that is to just ensure that the base class is initialized? 我一直在尝试理解这种用例,在这种情况下,我们经常从继承的类中调用基类构造函数,这样做的唯一目的是仅确保基类已初始化? Or, would there be other possible use cases? 还是会有其他可能的用例?

class Base:
    def __init__(self):
        print('Base.__init__')


class A(Base):
    def __init__(self):
        super().__init__()
        print('A.__init__')

is the sole purpose of doing that is to just ensure that the base class is initialized? 这样做的唯一目的是仅确保初始化基类?

Well yes, but what do you mean, just ? 嗯,是的,但你是什么意思, 公正

Assuming your base class has a reason to exist, it must do something. 假设您的基类有一个存在的理由,那么它必须一些事情。

Unless it's just a convenient collection of @staticmethod functions, whatever it does might depend on its __init__ having been called, because that's how class objects work. 除非它只是@staticmethod函数的便捷集合, @staticmethod它所做的任何事情都可能取决于其__init__调用,因为这就是类对象的工作方式。

Even if your base class has an empty __init__ today, it's sensible to call it, in case that changes in the future. 即使您的基类今天有一个空的__init__ ,也可以调用它,以防将来发生更改。

Or, would there be other possible use cases? 还是会有其他可能的用例?

The use case is to make sure that the base class part of your object is correctly initialized. 用例是确保对象的基类部分已正确初始化。 Without that, you can't safely call any of its non-static methods. 否则,您将无法安全地调用其任何非静态方法。

In principle your base class could do something tricksy in its __init__ (starting a background thread, or registering the instance with some singleton, or ... whatever). 原则上,您的基类可以在其__init__做一些棘手的事情(启动后台线程,或使用单例注册实例,或执行其他操作)。 So yes, there could be effects other than just assigning instance variables, but this is still part of initializing an object of that base class. 因此,是的,除了分配实例变量之外,还可能有其他效果,但这仍然是初始化该基类的对象的一部分。

In C++ or Java, the compiler will require you to call the base class constructor (either by automatically inserting a zero-argument call or by giving you an error). 在C ++或Java中,编译器将要求您调用基类构造函数(通过自动插入零参数调用或给您错误)。

Python requires you to call it yourself, as it is written : Python要求您自行调用它, 因为它是这样写的

If a base class has an __init__() method, the derived class's __init__() method, if any, must explicitly call it to ensure proper initialization of the base class part of the instance 如果基类具有__init__()方法,则派生类的__init__()方法(如果有)必须显式调用它,以确保实例的基类部分的正确初始化。

The reason why is a principle of object oriented design. 之所以是面向对象设计的原理。 An A "is-a" Base , which could also be written equivalently as an A "has-a" Base . A “是一个” Base ,其中也可以等效地写成A “具有-A” Base Unless you specifically want to interfere with the implementation of Base , you have to allow the object to be initialized as designed. 除非您特别想干扰Base的实现,否则必须允许按设计初始化该对象。 Skipping the constructor will leave the Base object improperly initialized, disappointing anyone who expects it to behave as a Base object ought to. 跳过构造函数将使Base对象的初始化不正确,这会使任何希望其表现为Base对象应有的行为的人感到失望。

When overriding a method besides the constructor, it is the programmer's discretion to delegate to the base class implementation or to override it entirely. 当重写除构造函数以外的方法时,程序员可以自行决定委托给基类实现还是完全重写它。 This can still lead to incorrect behavior --- several API docs I can think of pepper the documentation with "If you override this method, you should call super" for various methods. 这仍然可能导致错误的行为---我可以想到几个API文档,其中的各种方法都带有“如果重写此方法,则应调用super”作为胡椒文档。

The point of this is to initialize all the stuff the base class usually initializes. 这样做的目的是初始化基类通常初始化的所有东西。 For example, 例如,

class Base:
    def __init__(self, number):
        print('Base.__init__')
        self.number = number


class A(Base):
    def __init__(self, number, string):
        super().__init__(number)
        self.string = string
        print('A.__init__')

In this code example it's more obvious. 在此代码示例中,它更加明显。 When A calls the base constructor, the base constructor will initialize all of the stuff needed, such as self.number . A调用基本构造函数时,基本构造函数将初始化所有需要的东西,例如self.number This way, the rest of A 's initialization function can build on top of the base initialization function without any retyping. 这样, A的其余初始化函数可以在基本初始化函数的基础上构建,而无需重新键入。 In this example, A is building on top of Base by adding self.string on top of self.number . 在此示例中, A通过在self.string之上添加self.stringBase之上self.number

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

相关问题 元类:为什么方法不继承自基类? - Metaclasses: why method is not inherited from Base class? 为什么基类单例仍然多次调用构造函数? - Why does a base class singleton still call the constructor mulitple times? 轻松编辑继承类的基类变量 - Easily editing base class variables from inherited class 继承的类无法使用exec调用python中的基本方法 - inherited class can not call base method in python using exec Python继承的基类变量 - Python inherited base class variables 环境继承 Base class 条件 - Environment inherited Base class condition 更改子类中的默认构造函数参数值(从父类继承) - Change default constructor argument value (inherited from parent class) in subclass When using Generics types, how can I call an Attribute of an inherited class on the Base class instance with Python / Django? - When using Generics types, how can I call an Attribute of an inherited class on the Base class instance with Python / Django? 当继承 class 需要继承 ZA7F5F35426B9237811FC9231DZ 中的 class 时,如何从基础 class 继承? - How to inherit from a base class, when the inheriting class requires the inherited class in Python? 尝试在继承的类中导入基类时,为什么会出现导入错误(无法导入名称)? - Why do I get an Import Error( cannot import name) when trying to import the base class in the inherited class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM