這個,不管是什麼書都會這樣說,因為常常我們並不需要繼承,而只是想把類進行一定的擴展,而我們想擴展的屬性或方法對應的類都有,這個時候如果兩者是is a的關系,這種關系是確實存在的,那麼就可以使用繼承,不然一般都是建議使用復合。
如果我們隊一個類進行繼承的時候,我們如果對其內部的邏輯並不十分了解的時候,直接繼承的結果就是可能有些方法是類自己內部調用的,而我們在繼承這個方法的時候,可能會覆蓋某些方法,或者重載某些方法,或者加上了一些自己的邏輯,這樣就會吧原來的邏輯和我們自己的邏輯混雜起來,並且如果繼承的類內部有使用這個類的話,那麼就會調用我們自己寫的部分邏輯,那麼結果就變得不可預料了
這裡的建議是使用包裝類模式
package cn.xf.cp.ch02.item16; import java.util.Collection; import java.util.Iterator; import java.util.Set; public class ForwardingSet<E> implements Set<E> { /** * 這個類作為轉發類,內部通過復合的方式把set作為一個組件 */ private final Set<E> s; public ForwardingSet(Set<E> s) { this.s = s; } @Override public int size() { return s.size(); } @Override public boolean isEmpty() { return s.isEmpty(); } @Override public boolean contains(Object o) { return s.contains(o); } @Override public Iterator<E> iterator() { return s.iterator(); } @Override public Object[] toArray() { return s.toArray(); } @Override public <T> T[] toArray(T[] a) { return s.toArray(a); } @Override public boolean add(E e) { return s.add(e); } @Override public boolean remove(Object o) { return s.remove(o); } @Override public boolean containsAll(Collection<?> c) { return s.containsAll(c); } @Override public boolean addAll(Collection<? extends E> c) { return s.addAll(c); } @Override public boolean retainAll(Collection<?> c) { return s.retainAll(c); } @Override public boolean removeAll(Collection<?> c) { return s.removeAll(c); } @Override public void clear() { s.clear(); } }
這樣,我們在每個方法中調用了私有成員的方法,那麼私有成員對外部就是不可見的,它裡面的方法就不會和外面的方法混雜起來
package cn.xf.cp.ch02.item16; import java.util.Collection; import java.util.Set; /** * *功能:包裝類 *時間:下午9:58:36 *文件:InstrumentedSet.java *@author xiaof * * @param <E> */ public class InstrumentedSet<E> extends ForwardingSet<E> { private int addCount = 0; //用來統計set添加了多少元素 public InstrumentedSet(Set<E> s) { super(s); } @Override public boolean add(E e) { ++addCount; return super.add(e); } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } }