Java的單繼承多實現問題

最近突然想到一個老生常談的問題:爲什麼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();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章