欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java的单继承多实现问题

程序员文章站 2024-03-18 21:07:58
...

最近突然想到一个老生常谈的问题:为什么Java的类不支持多继承(接口支持的哈)?

抛开高司令不想搞得太复杂的说法,大概答案就是

  • 若子类继承的多个父类拥有相同的成员变量,子类在引用该变量时将无法判别使用哪个父类的成员变量。
  • 若子类继承的多个父类拥有相同的方法,同时子类并未覆盖该方法(若覆盖,则直接使用子类中该方法),那么调用该方法时将无法确定调用哪个父类的方法。

那么一个类实现了多个接口,就没有这个问题了吗?

在Java 8之前,很容易解释

  • 接口定义的变量都是常量,编译时就确定调用关系,使用接口名可以避免歧义。
  • 方法调用时始终只会调用实现类的方法,不存在歧义。

不过,Java 8之后接口可以拥有默认方法,一个类实现的多个接口具有相同的默认方法咋办咧?

没办法,只能要求子类做出选择了(重写该方法)。

相关代码证明

/**
 * 一个类实现的多个接口具有相同签名的方法
 *
 * @author Zhou Huanghua
 */
public class T implements A, B {
    public static void main(String[] args) {
        int i = A.CONSTANT; // 使用T.CONSTANT不能通过编译

        A a = new T();
        a.m1(); // 打印T#m1
        a.m2(); // 打印B#m2

        B b = new T();
        b.m2(); // 打印B#m2

        T t = new T();
        t.m2();// 打印B#m2
    }

    @Override
    public void m1() {
        System.out.println("T#m1");
    }

    /**
     * 必须重写,否则编译失败
     */
    @Override
    public void m2() {
        // 调用B的方法
        B.super.m2();
    }
}

interface A {
    int CONSTANT = 1;

    void m1();

    default void m2() {
        System.out.println("A#m2");
    }
}

interface B {
    int CONSTANT = 2;

    void m1();

    default void m2() {
        System.out.println("B#m2");
    }
}

/**
 * 接口支持多继承,如果有相同的默认方法必须重写
 */
interface C extends A, B {

    @Override
    default void m2() {
        A.super.m2();
    }
}