Java 的每個新版本都與之前的版本不同。下面是我們介紹過的材料變化的示例:在 Java 5 之前,該語言沒有
enum
s。 同樣,Java 8 與 Java 7 也有明顯不同。我們的大部分課程都是為該語言的第 7 版編寫的,但我們當然不會忽略重要的創新。由於我們已經在本課中討論了接口,因此我們將考慮一個更新——接口中的默認方法。您已經知道接口不實現行為。它的任務是描述所有實現它的對象必須具有的行為. 但是開發人員經常會遇到一個方法的實現在所有類中都相同的情況。讓我們考慮一下我們的舊車示例:
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 gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class F1Car implements Car {
@Override
public void gas() {
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 gas() {
System.out.println("This car accelerates differently!");
}
@Override
public void brake() {
System.out.println("This car decelerates differently!");
}
}
所有 99 種其他類型的汽車將執行默認方法,並且UnusualCar
作為例外的類不會破壞全局並冷靜地定義自己的行為。接口的多重繼承。如您所知,Java 不支持多重繼承。這件事情是由很多原因導致的。我們將在單獨的課程中詳細介紹它們。其他語言(例如 C++)確實支持它。如果沒有多重繼承,就會出現一個嚴重的問題:一個對象可以有幾種不同的特徵和“行為”。這是生活中的一個例子:我們是父母的孩子,我們是老師的學生,我們是醫生的病人。在生活中,我們扮演不同的角色,相應地,行為也不同:顯然,我們不會像與親密朋友交談那樣與老師交談。讓我們嘗試將其轉化為代碼。假設我們有兩個類:池塘和鳥舍。對於池塘,我們需要水禽;對於鳥舍,我們需要會飛的鳥。為此,我們創建了兩個基類:FlyingBird
和Waterfowl
。
public class Waterfowl {
}
public class FlyingBird {
}
相應地,我們會將繼承類的鳥送到FlyingBird
鳥舍,將繼承類的鳥送到Waterfowl
池塘。一切看起來都很簡單。但是我們要把鴨子送到哪裡呢?它會游泳和飛翔。而且我們沒有多重繼承。幸運的是,Java 支持接口的多種實現。雖然一個類不能繼承多個父類,但它可以輕鬆實現多個接口! 我們的鴨子既可以是飛鳥也可以是水禽:)我們只需要創建FlyingBird
接口Waterfowl
而不是類來實現預期的結果。
public class Duck implements FlyingBird, Waterfowl {
// The methods of both interfaces can be easily combined into one class
@Override
public void fly() {
System.out.println("Fly!");
}
@Override
public void swim() {
System.out.println("Swim!");
}
}
因此,我們的程序保留了類的靈活性,結合默認方法,我們定義對象行為的能力幾乎是無限的!:)
GO TO FULL VERSION