早期介面 (interface) 與抽象類 (abstract class) 最不同的在於介面沒有預設方法,但 Java 8 後介面可以有預設方法。如果要實現 abstract class 必須使用繼承 (extends),Java 是單一繼承,不過在實作 (implements) 介面上沒有數量限制。當 class 要實作介面是比繼承 abstract class 容易的,範例如下,String 要實作 Comparable 與 Serializable,如果都是介面,只需要使用 implements,但如果是繼承,就會出現 type hierarchy 的狀況。
// interface
public final class String
implements Serializable, Comparable<String>, CharSequence {
...
}
// 錯誤用法,abstract class
public abstract class Comparable<T> {
...
}
public abstract class Serializable extends Comparable {
...
}
public final String extends Serializable {
...
}
介面是定義 mixin (混合類型) 的理想選擇,Comparable 表示允許物件之間作比較,Serializable 則表示序列化的細節,String 同時實作兩者,表示它是屬於兩種的混合類型。介面間也可以使用繼承,像是歌手與作曲家,分別定義為兩個介面 (Singer 與 Songwriter),有些歌手本身也是作曲家,就實作兩個介面,也可以新增第三個介面的實作,然後在其中增加適合的方法。
public interface Singer {
AudioClip sing(Song s);
}
public interface Songwriter {
Song compose(int chartPosition);
}
public interface SingerSongwriter extends Singer, Songwriter {
AudioClip strum();
void actSensitive();
}
利用介面與 abstract class 的優點,提供骨架實現 (skeletal implementation) 的 class。實際應用像是 collections 中的 AbstractSet 及 AbstractList,當要實作客製化的 List 時,繼承 AbstractList 就能省去不少功夫,skeletal implementation 也能結合 wrapper class pattern,如果客製化 List 已經有繼承其它類,基於單一繼承原則,無法繼承 AbstractList,這時可以實作 List 介面,然後利用 helper class (private inner class) 繼承 AbstractList,最後在客製化 List 的實作方法中調用該 helper class。public interface List<E> {
boolean add(E e);
boolean remove(Object o);
}
public abstract class AbstractList<E> implements List<E> {
@Override
public boolean add(E e) {
// implementation
}
}
public class CustomizedList extends OtherClass implements List<E> {
private AbstractListDelegator delegator = ...;
private class AbstractListDelegator extends AbstractList {
@Override
public boolean remove(Object o) {
...
}
}
@Override
public boolean add(E e) {
return delegator.add(E e)
}
@Override
public boolean remove(Object o) {
return delegator.remove(o);
}
}
詳細範例https://dzone.com/articles/favour-skeletal-interface-in-java
http://web.mit.edu/6.005/www/fa14/classes/14-inheritance/#interfaces_and_abstract_classes
轉載請註明原文網址 https://cookieandcoketw.blogspot.com/2020/07/effective-java-20-interface-abstract.html
沒有留言:
張貼留言