杰瑞科技汇

Java如何调用父类的父类方法?

Java 不支持像 super.super.method() 这样的直接语法,我们需要分步操作:

Java如何调用父类的父类方法?-图1
(图片来源网络,侵删)
  1. 父类中,提供一个方法来调用其父类(也就是你的祖父类)的方法。
  2. 子类中,通过 super 关键字调用父类中刚刚创建的那个方法。

下面我们通过一个完整的例子来详细说明。

场景设定

假设我们有三个类,构成了一个继承链:

  • Grandparent (祖父类)
  • Parent (父类,继承自 Grandparent)
  • Child (子类,继承自 Parent)

我们的目标是:在 Child 类中调用 Grandparent 类里定义的 grandparentMethod()


步骤 1: 定义祖父类 和父类

我们定义 Grandparent 类和 Parent 类。

Java如何调用父类的父类方法?-图2
(图片来源网络,侵删)

Grandparent.java (祖父类)

public class Grandparent {
    public void grandparentMethod() {
        System.out.println("这是 Grandparent 类的 grandparentMethod() 方法。");
    }
}

Parent.java (父类)

public class Parent extends Grandparent {
    // Parent 类直接继承 Grandparent,所以它可以直接调用 grandparentMethod()
    // 为了让子类 Child 也能调用,我们在 Parent 中创建一个“桥梁”方法
    /**
     * 这个方法作为桥梁,用于调用祖父类的方法。
     * 子类 Child 可以通过调用这个方法来间接访问祖父类的方法。
     */
    public void callGrandparentMethod() {
        // 使用 super 关键字调用当前类的直接父类(即 Grandparent)的方法
        super.grandparentMethod();
    }
}

关键点解释 (在 Parent 类中):

  • Parent 类继承了 Grandparent,所以它可以直接访问 Grandparentpublicprotected 方法。
  • 我们在 Parent 类中创建了一个新的公共方法 callGrandparentMethod()
  • 在这个方法内部,我们使用 super.grandparentMethod() 来调用其父类(Grandparent)的方法。super 总是指向“直接父类”。

步骤 2: 定义子类并调用

我们定义 Child 类,并尝试调用祖父类的方法。

Java如何调用父类的父类方法?-图3
(图片来源网络,侵删)

Child.java (子类)

public class Child extends Parent {
    public void someMethod() {
        System.out.println("这是 Child 类的 someMethod() 方法。");
        // 现在我们想调用 Grandparent 的 grandparentMethod()
        // 我们不能直接 super.super.grandparentMethod(),这是错误的语法
        // 但我们可以通过调用父类 Parent 的“桥梁”方法来实现
        super.callGrandparentMethod(); 
    }
}

关键点解释 (在 Child 类中):

  • Child 类继承了 Parent 类。
  • 它无法直接看到 Grandparent 类,但它能看到 Parent 类的所有公共方法,包括我们刚刚创建的 callGrandparentMethod()
  • Child 类通过 super.callGrandparentMethod() 来调用父类的方法。
  • Parent.callGrandparentMethod() 被执行时,它会接着执行 super.grandparentMethod(),从而最终调用了 Grandparent 的方法。

步骤 3: 测试代码

让我们创建一个 Main 类来测试整个过程。

Main.java

public class Main {
    public static void main(String[] args) {
        Child child = new Child();
        child.someMethod();
    }
}

运行结果

执行 Main.java,控制台会输出:

这是 Child 类的 someMethod() 方法。
这是 Grandparent 类的 grandparentMethod() 方法。

这个结果清晰地展示了调用链:Child.someMethod() -> Parent.callGrandparentMethod() -> Grandparent.grandparentMethod()


总结与最佳实践

  1. 没有直接语法:Java 中不存在 super.super 这样的语法,所有对父类方法的调用都必须通过直接父类。

  2. “桥梁”模式:解决这个问题的标准方法是在父类中创建一个“桥梁”方法,这个方法的作用就是调用其父类(你的祖父类)的方法。

  3. 访问修饰符的重要性

    • Grandparent.grandparentMethod()private 的,Parent 类也无法访问它,自然也就无法作为桥梁。
    • Grandparent.grandparentMethod()protectedpublic 的,Parent 类就可以访问它。
    • 同样,你在 Parent 类中创建的“桥梁”方法(如 callGrandparentMethod)也必须是 publicprotected,才能被 Child 类通过 super 访问。
  4. 设计思考:虽然技术上可以实现,但在日常开发中,过度依赖这种调用方式可能会增加类的耦合度,使继承关系变得复杂,在考虑使用这种模式前,可以思考一下:

    • 是否可以通过组合(Composition)或委托(Delegation)来解决问题,这可能更灵活。
    • 这个方法是否真的需要被“孙类”调用?Grandparent 的方法只应由 Parent 来使用,那么就不需要暴露给 Child

另一种情况:父类覆盖了祖父类的方法

Parent覆盖(Override)Grandparent 的方法,情况会稍有不同。

修改后的 Parent.java

public class Parent extends Grandparent {
    @Override
    public void grandparentMethod() {
        System.out.println("这是 Parent 类覆盖后的 grandparentMethod() 方法。");
    }
    // 桥梁方法依然有效
    public void callGrandparentMethod() {
        super.grandparentMethod(); // 这里调用的是被覆盖前的 Grandparent 的方法
    }
}

测试代码不变,运行结果会变为:

这是 Child 类的 someMethod() 方法。
这是 Grandparent 类的 grandparentMethod() 方法。

即使 Parent 覆盖了 grandparentMethod()Parent 类中的 super.grandparentMethod() 依然会精确地调用 Grandparent 的原始版本,这正是 super 关键字的强大之处。

分享:
扫描分享到社交APP
上一篇
下一篇