|
||||||||||||||||||||||||||
| 前のページ 1 2 3 4 次のページ | ||||||||||||||||||||||||||
| abstractメソッドを利用する(C_IHT002) | ||||||||||||||||||||||||||
|
抽象クラスは、インターフェースと同様にそれ単体ではインスタンス化できないクラスです。 インターフェースとの違いは部分的に実装を提供可能であるという点です。実装を提供しないメソッドにはabstract修飾子を付与して抽象メソッドとすることで、サブクラスでの実装を強制させることができます。 特殊なケース(注1)を除いて、実装が空であるメソッドを作成すべきではありません。空メソッドの実装をサブクラスでオーバーライドするという意図があるならば、抽象メソッドとすることで、その意図を明確にする必要があります。抽象メソッドとせずに空メソッドを定義していた場合、サブクラスでの実装を忘れる可能性があります。
※注1:
空メソッドを提供する典型的な例としては、NullObjectパターンがあります。詳細は、下記のURLなどを参照してください。
http://www.hyuki.com/dp/dpinfo.html#NullObject |
||||||||||||||||||||||||||
| スーパークラスでprivate宣言されているメソッドと同じ名前のメソッドをサブクラスで定義しない(C_IHT003) | ||||||||||||||||||||||||||
|
スーパークラスのインスタンスメソッドがprivateである場合、サブクラスで同一のシグニチャを持つインスタンスメソッドを定義することが可能です。この際、これらのメソッドに「オーバーライド」の関係はなく、各々のクラスに従属する独立したメソッドとして動作します。 スーパークラスのインスタンスメソッドがprivateである場合、サブクラスで同一シグニチャを持つインスタンスメソッド、つまりは「同一名称のメソッド」を定義すべきではありません。これは、C_IHT001の規約で説明した「継承によるフィールドの隠蔽」と同様にサブクラスの可読性を低下させる原因となります。 一方、スーパークラスのインスタンスメソッドの可視性をprivateに変更する際には、細心の注意を払う必要があります。当該メソッドがサブクラスによってオーバーライドされている場合、この変更にともないオーバーライドの関係が絶たれることになります。場合によっては、コンパイルエラーが発生しないこともあるため、変更者が意図していなかった箇所で影響がでるといった危険性があります。 |
||||||||||||||||||||||||||
| equals()メソッドを実装した場合は、コレクションクラスに格納することを想定してhashCode()メソッドも実装する(C_IHT004) | ||||||||||||||||||||||||||
|
ハッシュテーブルは、「一対のキーと値」として表現される要素を格納するデータ構造です。この構造に基づいたコレクションクラス(HashMap、HashSet、Hashtableなど)を利用する際、これらのコレクションクラスの動作を保証するためには、キーとなるクラスのequals()メソッドおよびhashCode()メソッドが正しく定義されている必要があります。 従ってequals()メソッドを実装した際には、こうしたコレクションクラスでの利用を想定し、hashCode()メソッドを実装するべきです。本規約に違反した場合、コレクションクラスの動作が保証されずバグとなる危険性があります。 それでは、Java2以降のコレクションクラスであるjava.util.HashMapを利用したサンプルプログラムを見てみましょう。 下記サンプルでは、コレクションのキーとなるクラスIDNumberが定義されています。IDNumberにはequals()メソッドのみが再定義(オーバーライド)され、hashCode()メソッドは定義されていません。そのためObjectクラスのhashCode()メソッドが継承されます。 HashMapを利用したサンプルプログラム |
||||||||||||||||||||||||||
public final class IDNumber {
|
||||||||||||||||||||||||||
|
equals()メソッドは、HashMapコレクションに値を格納する際に利用したキー(initialKey)と取得に利用したキー(findKey)が等しい(1)としているにも関わらず、HashMapコレクションからは値"Oka"は返却されず、"null"が返されました(2)。 先ほど、ハッシュテーブルに基づくコレクションの動作が保証されるには、「キーとなるクラスのhashCode()メソッドとequals()メソッドが正しく定義されている」必要があると説明しましたが、これらのメソッドが正しく定義されているとは、hashCode()がequals()の結果に対して、次の条件を満たす整数値を返すことを意味します。
表1:メソッドの正しく定義
Objectクラスのequals()メソッドは、nativeメソッドでその実装はJava VMに依存しますが、異なるオブジェクト参照を持つinitialKeyとfindKeyは異なる整数値を返します。このため、表1の2が満たされずに値"Oka"が取得されなかったことになります。 表1の1と2を満たすhashCode()メソッドの最も簡単な実装は、IDNumberクラスにおいて"return 0;"であるhashCode()メソッドを再定義することです。これにより、値"Oka"が取得できるようになります(注2)。
※注2:
この実装はパフォーマンス面に問題があります。パフォーマンスを考慮した実装を書くには高度な知識が必要となります。この問題に対するひとつの解は、Jakarta Commonsプロジェクトで提供されているLangコンポーネントを利用することです。
Langコンポーネントの利用方法は、下記の書籍などを参考にしてください。 「Jakarta Commonsクックブック -Javaプロジェクト必須のレシピ集」 |
||||||||||||||||||||||||||
|
前のページ 1 2 3 4 次のページ |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||

