2020/07/24

[筆記] Effective Java #20 介面優於抽象類

Effective Java 3rd 簡體中文版筆記 #20 介面優於抽象類
早期介面 (interface) 與抽象類 (abstract class) 最不同的在於介面沒有預設方法,但 Java 8 後介面可以有預設方法。如果要實現 abstract class 必須使用繼承 (extends),Java 是單一繼承,不過在實作 (implements) 介面上沒有數量限制。當 class 要實作介面是比繼承 abstract class 容易的,範例如下,String 要實作 ComparableSerializable,如果都是介面,只需要使用 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 同時實作兩者,表示它是屬於兩種的混合類型。介面間也可以使用繼承,像是歌手與作曲家,分別定義為兩個介面 (SingerSongwriter),有些歌手本身也是作曲家,就實作兩個介面,也可以新增第三個介面的實作,然後在其中增加適合的方法。
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 中的 AbstractSetAbstractList,當要實作客製化的 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

沒有留言:

張貼留言