介面

      在〈介面〉中尚無留言

介面(Interface)

完全不相關的類別, 卻擁有相同的功能. 比如鳥跟飛機, 一個是生物, 一個是機械, 但卻同樣擁有 “飛” 的功能. 這有種群組的功能.

另外也可以想成, 二個完全不相關的類別, 但擁有相同的方法, 此時可以用Interface讓每個類別實作.

這種觀念有點像具某種功能一樣. 比如皮卡丘是神奇寶貝, 是爬蟲類. 而劍魚也是神奇寶貝, 但屬於水中生物.

其實介面是為了彌補Java單一繼承的缺陷, 也就是多型的部份. 多型會在日後的章節中詳述. 所以在有多重繼承的語言中, 比如Python, 就沒有interface了.

介面同時也跟抽象類別一樣, 規定繼承者必需遵守的契約

interface Land{
    void walk();
}
interface Water{
    void swin();
}
abstract class Pokemon{
    abstract public void setLevel(int l);
}
class Pikachi extends Pokemon implements Land{
    @Override
    public void walk() {
        System.out.println("用爬的");
    }
    @Override
    public void setLevel(int level){}
}
class Fish extends Pokemon implements Water{
    @Override
    public void swin() {
        System.out.println("用游的");
    }
    public void setLevel(int level){}
}

interface修飾子

interface中的方法, 一定是 abstract public, 系統會自動加入, 也可以手動加入. 不過請注意, C#是不允許雞婆的手動加入.

若介面的抽象方法宣告為private or protected, 則會編譯錯誤

    public interface Returnable{
        abstract public String doReturn();
    }

子類別實作

子類別繼承了介面, 此時的關鍵字就不再是extends了, 而是 implements.

class Pikachu implements Land{}

此時的Pikachu就必需實作Land的所有抽象方法.

實作多個介面

為什麼要實作多個介面呢?? 讓我們思考一下青蛙 class Frog, 它到底是要實作Land, 還是Water? 青蛙是兩棲生物嘛, 所以當然是一起實作. 多個介面中間, 以 “,” 隔開

interface Land{}
interface Water{}
class Frog implements Land, Water{}

抽象類別與介面同時實作

類別可以在繼承類別或抽象類別時, 又同時實作多個介面. 但此類別就必需實作抽象類別及所有介面的所有抽象方法

abstract class Pokemon{
    public int level;
    protected abstract void setLevel(int l);
}
interface Land{
    void setWalk();
}
interface Water{
    void setSwinning();
}
class Frog extends Pokemon implements Land, Water{
    @Override
    protected void setLevel(int l) {}
    @Override
    public void setWalk() {}
    @Override
    public void setSwinning() {}
}

多型

若要使用interface裏的方法, 則物件參考必需是此Interface或是implement此介面的類別才可以, 若物件參考是沒實作此介面的類別則無法存取

  public static void main(String[] args) {
      Pokemon p1=new Pikachi();
      //p1.walk();
      Pikachi p2=new Pikachi();
      p2.walk();
  }

p1屬Pokemon, 跟Land沒關係, 所以不能使用 walk();
p2屬Pikachi, is a Land, 所以可以使用walk();

 介面的變數

介面內的變數, 一定是常數欄位(constant fields), 系統會自動視為public static final 變數. 所以變數都要自行給定初始值.

    interface Running{
        public static final String WARNING="這是爬蟲類";
        public void run();
    }

 介面繼承

青蛙是兩棲生物, 所以實作了Land及Water二個介面. 那可以將Land及Water變成一個 Amphibian 介面, 再給青蛙實作嗎. 是的, 介面可以繼承介面, 而且是可以多重繼承的. 

請注意喔, 介面的繼承是 extends.

abstract class Pokemon{
    public int level;
    protected abstract void setLevel(int l);
}
interface Land{
    void setWalk();
}
interface Water{
    void setSwinning();
}
interface Amphibian extends Land, Water{}
class Frog extends Pokemon implements Amphibian{
    @Override
    protected void setLevel(int l) {}
    @Override
    public void setWalk() {}
    @Override
    public void setSwinning() {}
}

介面與抽象類別的抽象方法相衝

類別可以implements 多個介面. 試想, 若每個介面都有相同的方法時, 那類別要怎麼實作? 其實不相衝, 只要實作一個就好了

介面總結

1. 介面只能有抽象方法, 不能有實体代碼
2. 介面的抽象方法一定是abstract public
3. 介面可以有變數, 但系統會自動加入 final public static

考題

有二個介面及一個抽象類別
interface Land{}
interface Water{}
abstract class Pokemon{}
請問以下何者是正確的
1. class Frog implements Pokemon{}
2. class Frog extends Pokemon{}
3. class Frog extends Land{}
4. class Frog implements Land, Water{} 
5. class Frog extends Pokemon implements Land, Water{}
6. interface Amphibian implements Land{}
7. interface Amphibian extends Land, Water{}
Ans:
2, 4, 5, 7

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *