You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

子类类方法调用父类类方法的正确方式及super函数误区解析

子类调用父类类方法时super()失效的原因与优化方案

我有一个父类Rectangle,支持两种初始化方式:标准的__init__方法,以及类方法with_vectors通过正交向量初始化。子类Square继承自Rectangle,我希望它也能实现类似的双初始化结构,并且复用父类的with_vectors逻辑,但使用super()调用时出现错误,只有直接调用Rectangle.with_vectors能运行,但不确定这种方式是否正确。

示例代码:

import numpy as np

def scalar_product(vector_a: tuple, vector_b: tuple):
    if len(vector_a) != len(vector_b):
        raise ValueError(f"The vectors provided do not have the same dimensionality.")
    return (np.array(vector_a) * np.array(vector_b)).sum()


class Rectangle:
    def __init__(self, side: float, width: float):
        self.side = side
        self.width = width

    @classmethod
    def with_vectors(cls, vector_a: tuple, vector_b: tuple):
        if scalar_product(vector_a, vector_b) != 0:
            raise ValueError(f"The vectors must be orthogonal")
        side = np.sqrt((np.array(vector_a) ** 2).sum())
        width = np.sqrt((np.array(vector_b) ** 2).sum())
        return cls(side, width)

    def get_area(self):
        return self.side * self.width

class Square(Rectangle):
    def __init__(self, side: float):
        super().__init__(side, side)

    @classmethod
    def with_vectors(cls, vector_a: tuple):
        vector_b = (vector_a[1], -vector_a[0])
        # return super().with_vectors(vector_a, vector_b)   # TypeError: Square.__init__() takes 2 positional arguments but 3 were given
        # return super(Rectangle, cls).with_vectors(vector_a, vector_b)   # AttributeError: 'super' object has no attribute 'with_vectors'
        return Rectangle.with_vectors(vector_a, vector_b)  # 能运行但返回Rectangle实例

一、你对super()的误解点

  1. 第一个错误的原因:
    当调用super().with_vectors(vector_a, vector_b)时,父类的with_vectors方法中会执行cls(side, width),这里的cls是当前子类Square(类方法的cls参数会传递调用该方法的类)。而Square的__init__只接受1个位置参数,传入side和width两个参数自然触发TypeError。

  2. 第二个错误的原因:
    super(Rectangle, cls)的作用是跳过Rectangle类,直接查找Rectangle的父类(即object),而object类并没有with_vectors方法,因此抛出AttributeError。

二、当前直接调用方式的问题

你现在用Rectangle.with_vectors(vector_a, vector_b)确实能运行,但它返回的是Rectangle实例,而不是Square实例,这不符合子类Square的设计预期——用户调用Square.with_vectors应该得到正方形对象,而不是矩形对象。

三、更合适的实现方案

方案1:兼容父类调用的子类构造方法

修改Square的__init__,让它支持可选的width参数,这样父类with_vectors中的cls(side, width)就能正常调用,同时保证正方形的边长一致:

class Square(Rectangle):
    def __init__(self, side: float, width: float = None):
        # 强制width与side保持一致,确保是正方形
        actual_width = side if width is None else side
        super().__init__(side, actual_width)

    @classmethod
    def with_vectors(cls, vector_a: tuple):
        vector_b = (vector_a[1], -vector_a[0])
        return super().with_vectors(vector_a, vector_b)

此时调用Square.with_vectors会返回Square实例,同时复用了父类的向量验证和边长计算逻辑。

方案2:拆分父类逻辑,复用核心计算

把父类with_vectors中的验证和边长计算逻辑拆成静态方法,子类直接复用核心逻辑,自己创建实例:

class Rectangle:
    def __init__(self, side: float, width: float):
        self.side = side
        self.width = width

    @staticmethod
    def _validate_and_calculate_sides(vector_a: tuple, vector_b: tuple):
        if scalar_product(vector_a, vector_b) != 0:
            raise ValueError(f"The vectors must be orthogonal")
        side = np.sqrt((np.array(vector_a) ** 2).sum())
        width = np.sqrt((np.array(vector_b) ** 2).sum())
        return side, width

    @classmethod
    def with_vectors(cls, vector_a: tuple, vector_b: tuple):
        side, width = cls._validate_and_calculate_sides(vector_a, vector_b)
        return cls(side, width)

    def get_area(self):
        return self.side * self.width

class Square(Rectangle):
    def __init__(self, side: float):
        super().__init__(side, side)

    @classmethod
    def with_vectors(cls, vector_a: tuple):
        vector_b = (vector_a[1], -vector_a[0])
        side, _ = cls._validate_and_calculate_sides(vector_a, vector_b)
        # 正方形边长相等,直接取一个值即可
        return cls(side)

这种方式更灵活,既复用了父类的验证逻辑,又严格遵循了Square的构造规则,返回的是纯正的Square实例。

内容的提问来源于stack exchange,提问作者Perceval Desforges

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 02:19:55