在子类中启动超类对象

Posted

技术标签:

【中文标题】在子类中启动超类对象【英文标题】:initiate superclass object in subclass 【发布时间】:2021-06-03 05:14:00 【问题描述】:

有人可以向我解释一下 child_2 类中 super() 的含义吗?我发现 super() 启动是在 child_2 而不是 child_1 中拾取 convert_id() 函数,这有点违反直觉。我想通过调用super(),假设是使用class_1中的函数来初始化对象。

from abc import ABC, abstractmethod

class base(ABC):
    @abstractmethod
    def convert_id(self, id):
        pass

class child_1(base, ABC):
    def __init__(self, id):
        self.new_id = self.convert_id(id)

    def convert_id(self, id):
        return id

class child_2(child_1):
    def __init__(self, id):
        self.id = id
        super().__init__(id=self.id)

    def convert_id(self, id):
        return id+1

test = child_2(0)
print(test.new_id)
1

【问题讨论】:

【参考方案1】:

这是在带有继承的面向对象编程中的正常、预期和基本的行为方式。

这个想法是您的专用类(继承的类)可以专门化特定方法。一般模式是超类中的方法可以协调各种其他方法的调用以执行相关实例的特定任务 - 如果专门的子类希望通过重写来改进其中一种方法,那就是调用的方法.

在运行时术语中,child_1.__init__ 接收的 selfchild_2 的一个实例(它也恰好是 child_1 的一个实例) - 但是在接收到的对象中调用的方法将从 child_2 解决。 如果您将child_1.__init__ 中的“自我”视为child_1 的实例,那只是“违反直觉”。这种“强制转换”永远不会发生,在 Python 中自然也不可行。

现在,如果您的代码中有一个需要这种行为的模式:child_1 中的 __init__ 仅调用 child_1 中定义的方法,而不是子类中的覆盖方法,这是可行的"name mangling" 机制:如果方法或属性以两个下划线 (__) 开头,编译器会将类名烘焙到该方法或属性名中,以一种不会被意外覆盖的方式(而__ 的提示让程序员清楚地知道它不应该被覆盖)。在 Python 以外的其他语言中,这种行为是通过使用“私有”方法实现的:子类本身无法访问的方法(与“受保护”不同)。

及时:此行为与您从 abc.ABC 或从其使用的自定义元类继承的事实无关 - 这就是语言的工作原理。

换句话说,如果你调用你的方法__convert_id而不是convert_id,你所期望的行为将会发生。但请记住,这不是继承的自然行为,它只是一种比简单地允许方法被覆盖更少用途的可能方式。

【讨论】:

以上是关于在子类中启动超类对象的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在超类对象上调用子类的方法?

马凯军201771010116《面向对象程序设计(java)》第七周学习总结

关于超类引用和子类对象的混淆

调用对象方法传递超类期望子类

Java多态如何调用子类对象的超类方法

从超类对象初始化子类实例