今度はEFJでは、継承の危険性を説明しております。
継承はオブジェクト指向をやぶる危険性を内包しております。
このため、オーバーライドなどを使用する際には気を付ける必要があります。
1.メソッドをオーバーライドする時は、どのような機能が実装されるのかを正確に文免で残してください。
/**
* {@inheritDoc}
*
* <p>This implementation iterates over the collection looking for the
* specified element. If it finds the element, it removes the element
* from the collection using the iterator's remove method.
*
* <p>Note that this implementation throws an
* <tt>UnsupportedOperationException</tt> if the iterator returned by this
* collection's iterator method does not implement the <tt>remove</tt>
* method and this collection contains the specified object. * * @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public boolean remove(Object o)
}
上記はjava.util.AbstractCollectionのremove()メソッドです。
この内容を読んでみると、removeが呼び出されると、Iteratorが使われることを分かります。
「サブクラスでIteratorをオーバーライドする際に注意しなければならない」という事実を知ることができます。
もちろん、このような詳細だけでは足りず、
クラス内部動作に介入することができるフック(hooks)を慎重に選んだ後、
protectedメソッドに提供する必要があります。
フック(hook)メソッドと選択的にオーバーライドすることができるメソッドを指します。
分かりやすく説明するため図を作ってみました。
subクラスの中で、finalメソッドはオーバーライドが不可能であり、
abstractは必ずオーバーライドしなければなりません。
publicはオーバーライドするかどうかを継承する人が定められます。
フック(hook)メソッドとは、
このように継承するかどうかを決めることができるメソッドを指します。
また、コンストラクタでオーバーライド可能なメソッドを呼び出してはいけません。
public class Super {
public Super() {
overrideMe();
}
public void overrideMe() {
}
}
public class Sub extends Super {
private final Date date;
Sub() {
date = new Date();
}
@Override
public void overrideMe() { System.out.println(date); }
public static void main(String[] args) {
Sub sub = new Sub();
sub.overrideMe();
}
}
継承をすると、superクラスのコンストラクタが自動的に呼び出されることをご存知かと思います。
このコードで、dateは二度呼び出されることが予想されますが
実際には、最初の呼び出し時には何も呼び出されません。
subのdateが呼び出される前に、superクラスのコンストラクタが呼び出され
overrideMeが呼び出されるからです。
댓글 없음:
댓글 쓰기