在__init__()中调用重写的方法安全吗?

12 投票
1 回答
1492 浏览
提问于 2025-04-16 22:26

这是对这个问题的后续讨论:

《Effective Java》第2版,第17条:为继承设计和文档,或者禁止继承:

为了允许继承,一个类必须遵守一些额外的限制。构造函数不能直接或间接调用可以被重写的方法。如果违反这个规则,程序就会出错。父类的构造函数在子类的构造函数之前运行,所以子类中的重写方法会在子类构造函数运行之前被调用。如果重写的方法依赖于子类构造函数完成的任何初始化,那么这个方法就不会按预期工作。

因为我们只讨论Java构造函数的初始化部分,我认为可以安全地将Java的构造函数与Python的__init__()进行比较。

我猜测,在Python中,我可以灵活决定何时调用(在这种情况下是初始化我当前类的数据属性之后)我的父类的__init__(),而在Java中,super()必须是构造函数调用中的第一条语句,所以我可能可以安全地在__init__()中调用重写的方法?

如果我对上述猜测是正确的,那么作为父类设计者,我不就得听从子类设计者的安排吗?如果子类设计者在初始化他的数据属性之前调用了我的__init__(),而这些数据属性会被他重写的方法使用,那么我调用那个方法时,就会导致程序出错!

1 个回答

6

我可以放心地在 __init__() 方法中调用被重写的方法吗?

可以的。在 __init__() 方法执行之前,self 已经绑定好了,也就是说对象已经创建好了。

祖先类的设计者会被我的子类设计者摆布吗?

这是普遍适用的,跟 __init__() 或其他任何东西都没有关系。

子类的开发者可以做任何事情。而且,这里是 Python:他们可以看到你的源代码,还可以修改它。

如果子类的设计者在初始化他的数据属性之前调用了我的 __init__(),而这些数据属性会被他重写的方法使用,那么当我调用那个方法时,程序就会出错!

没错。这个问题的出现是因为子类设计者选择了一个你已经在使用的名字。通过这个名字的选择,他们确保了程序会出错。

撰写回答