每個新版本的 Java 都與以前的版本不同。
因此,Java 8 與 Java 7 明顯不同。當然,我們不會忽視重要的創新。由於我們在本課中討論接口,讓我們考慮對該語言的一個更新:接口中的默認方法。您已經知道接口不實現行為。它的目的是描述實現該接口的所有對像中必須存在的行為。但是開發人員經常會遇到一個方法的實現在所有類中都相同的情況。讓我們看看我們的舊車示例:
enums
作為我們所介紹材料的這種變化的一個例子,該語言在 Java 5 之前 沒有。
public interface Car {
public void gas();
public void brake();
}
public class Sedan implements Car {
@Override
public void gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class Truck implements Car {
@Override
public void go() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class F1Car implements Car {
@Override
public void go() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
您認為這段代碼的主要問題是什麼?您可能注意到我們寫了一堆重複的代碼!這是編程中的常見問題,應該避免。在 Java 8 發布之前沒有特定的解決方案是另一回事。當該版本發佈時,可以定義默認方法並在接口內實現它們!方法如下:
public interface Car {
public default void gas() {
System.out.println("Gas!");
}
public default void brake() {
System.out.println("Brake!");
}
}
public class Sedan implements Car {
}
public class Truck implements Car {
}
public class F1Car implements Car {
}
現在,所有汽車都相同的gas()
和方法已移至界面中,從而消除了重複代碼的需要。brake()
而且這些方法在每個類中都可用!
public class Main {
public static void main(String[] args) {
F1Car f1Car = new F1Car();
Sedan sedan = new Sedan();
Truck truck = new Truck();
truck.gas();
sedan.gas();
f1Car.brake();
}
}
如果有 100 個類具有一個gas()
方法,但其中只有 99 個應該具有相同的行為怎麼辦?這會破壞一切嗎?默認方法在這種情況下不起作用嗎?當然不是 :) 默認接口方法可以被覆蓋。
public class UnusualCar implements Car {
@Override
public void go() {
System.out.println("This car accelerates differently!");
}
@Override
public void brake() {
System.out.println("This car slows down differently!");
}
}
其餘99款車型均採用默認方式,而UnusualCar
班級是個例外。在不破壞大局的情況下,它會冷靜地定義自己的行為。接口中的多重繼承。如您所知,Java 中沒有多重繼承。這件事情是由很多原因導致的。我們將在單獨的課程中詳細討論它們。在其他語言中,例如 C++,情況正好相反。沒有多重繼承是一個嚴峻的挑戰,因為同一個對象可以有幾個不同的特徵和行為。例如,我們是父母的孩子,老師的學生,醫生的病人。在現實生活中,我們扮演著不同的角色,因此行為也不同:顯然,我們與老師的互動不同於與親密朋友的互動。讓我們嘗試將這種情況轉化為代碼。假設我們有兩個類:Pond 和 Aviary。池塘需要游泳的鳥,而鳥舍需要飛翔的鳥。為了表示這一點,我們創建了兩個基類:FlyingBird
和Waterfowl
。
public class Waterfowl {
}
public class FlyingBird {
}
因此,我們會將繼承的鳥類送到FlyingBird
鳥舍,而那些繼承的鳥類Waterfowl
將進入池塘。一切似乎都很簡單。但是如果我們需要在某處定義一隻鴨子,我們應該怎麼做呢?鴨子既會游泳也會飛。但是我們沒有多重繼承。幸運的是,Java 支持接口的多種實現。如果一個類不能繼承多個父類,實現多個接口很容易!我們的鴨子可以是飛翔的鳥,也可以是游泳的鳥 :) 為了達到預期的效果,我們需要做的只是創建FlyingBird
接口Waterfowl
而不是類。
public class Duck implements FlyingBird, Waterfowl {
// Methods of both interfaces combine easily into one class
@Override
public void fly() {
System.out.println("Flying!");
}
@Override
public void swim() {
System.out.println("Swimming!");
}
}
這意味著我們的程序保留了靈活管理班級的能力。當我們將其與默認方法結合使用時,我們確定對象行為的能力幾乎變得無限!:)
GO TO FULL VERSION