Java接口-多重繼承-Java編程思想

概述

最近把Java基礎知識梳理了一下,發現了一些以前理解有偏差的地方,記錄在此。

疑問

  • 一個類同時繼承基類和多個接口時,該類中是否可以不實現接口中的方法?
  • 一個類同時實現多個接口,能否向上轉型到各接口?
  • 一個類同時實現多個接口,接口中的方法簽名是否可以保持一樣?

代碼解惑

package think.in.java.interfaces;//: interfaces/Adventure.java
// Multiple interfaces.

import static net.mindview.util.Print.print;

interface CanFight {
    void fight();
}

interface CanSwim {
    void swim();
}

interface CanFly {
    void fly();
}

class ActionCharacter {
    public void fight() {
        print("base class fight method");
    }
}

/**
 * 繼承一個類、多個接口
 */
class Hero extends ActionCharacter
        implements CanFight, CanSwim, CanFly {
    public void swim() {
        print("sub class swim method");

    }

    public void fly() {
        print("sub class fly method");
    }

//  @Override
//  public void fight() {
//      print("sub class fight method");
//  }
}

public class Adventure {
    public static void t(CanFight x) {
        // 如果 Hero 沒有重寫父類的fight方法,則調用父類的fight方法
        x.fight();
    }

    public static void u(CanSwim x) {
        x.swim();
    }

    public static void v(CanFly x) {
        x.fly();
    }

    public static void w(ActionCharacter x) {
        // Hero 沒有重寫父類的fight方法,則調用父類的fight方法
        x.fight();
    }

    public static void main(String[] args) {
        Hero h = new Hero();
        t(h); // Treat it as a CanFight
        u(h); // Treat it as a CanSwim
        v(h); // Treat it as a CanFly
        w(h); // Treat it as an ActionCharacter
    }
} ///:~

輸出:

base class fight method
sub class swim method
sub class fly method
base class fight method

一個類同時繼承基類和多個接口時,該類中是否可以不實現接口中的方法?

我們發現,Hero實現了CanFight接口,CanFight接口中定義了fight()方法。但是在Hero中卻並沒有實現該方法。
其實這個問題也好理解,因爲Hero類繼承了ActionCharacter基類,而ActionCharacter基類中實現了fight()方法。父類的方法,子類自然有權限使用。
所以,在CanFight xActionCharacter x引用調用fight()方法時,自然引用到了基類的fight()方法。

一個類同時實現多個接口,能否向上轉型到各接口?

這個從代碼中我們可以看到,Hero子類可以作爲參數傳遞給CanFightCanSwimCanFly等類型。所以,是可以向上轉型到各接口的。

Java允許實現多個接口,而不是繼承多個類。這消除了我們在組合相同基類實現時使用的兩個相同成員的不確定性。
看代碼:

/**
 * 第一個接口
 */
interface BaseInterface {
    void f();
}

interface IntermediateInterface1 extends BaseInterface {
    void f();
}

interface IntermediateInterface2 extends BaseInterface {
    void f();
}

/**
 * 多重繼承接口
 */
interface CombinedInterface
        extends IntermediateInterface1, IntermediateInterface2 {
    void f();
}

class CombinedImpl implements CombinedInterface {
    public void f() {
        System.out.println("CombinedImpl.f()");
    }
}

/**
 * 創建一個接口,並從該接口繼承兩個接口,然後從後面兩個接口多重繼承第三個接口
 */
public class E13_Diamond {
    public static void main(String[] args) {
        new CombinedImpl().f();
    }
} /* Output:
         CombinedImpl.f()
         *///:~

一個類同時實現多個接口,接口中的方法簽名是否可以保持一樣?

CombinedImpl實現了CombinedInterface,而CombinedInterface又分別繼承了IntermediateInterface1IntermediateInterface2接口,IntermediateInterface1IntermediateInterface2接口繼承了BaseInterface接口。
而這些接口都有’f()’方法。所以是可以的。
試想一下,如果同時繼承兩個基類,而碰巧兩個基類中有同樣的方法。那麼向上轉型後,調用該方法,程序是不是就不知道該調用A基類的方法還是B基類的方法了呢? 不過接口是可以這麼幹的。

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