LoginSignup
2
1

More than 5 years have passed since last update.

Item 41: Use marker interfaces to define types

Posted at

41.型定義のためにマーカーインターフェースを使うべし

マーカーインターフェースとは、メソッド定義を含まず、単にそのインターフェースを実装したクラスが特定の属性を持っていることを示すためのものである。
例として、Serializableインターフェースがあげられる(12章)。このインターフェースを実装することで、そのクラスのインスタンスはObjectOutputStreamに書き込み可能であることが示される。

マーカーアノテーション(Item39)の登場で、マーカーインターフェースは時代遅れになったように思えるかもしれないが、それは誤りである。
マーカーインターフェースはマーカーアノテーションに比べて、2つの点でアドバンテージがある。
1つ目はマーカーインターフェースは型を定義するが、マーカーアノテーションはしないことである。これによって、マーカーアノテーションでは実行時まで捕捉できないエラーがコンパイル時に捕捉できることとなる。
Javaのシリアライゼーション機能では、型がシリアライザブルであることを示すために、Serializableマーカーインターフェースを使用している。ObjectOutputStream.writeObjectメソッドでは、渡されたオブジェクトをシリアライズするが、その引数はシリアライザブルであることを求める。このメソッドの引数がSerializableであれば(実際にはObjectをとる)、不適切な型の引数が来た場合にコンパイルで検知できる。
2つ目はマーカーインターフェースの方がより簡潔に対象を絞れることにある。
マーカーアノテーションのターゲットがElementType.TYPEである場合は全てのクラスとインターフェースが対象となるが、マーカーインターフェースの場合はそれを実装しているクラスに限られる。
Set インターフェースは、そのような制限するマーカーインターフェースである。
SetはCollectionのサブタイプにのみ実装されるが、Collectionで定義されたメソッドに何も付け加えていない。SetはCollectionのメソッドの一部を再定義しているので、一般にマーカーインターフェースとはみなされていない。
しかし、特定のインターフェースのサブタイプにのみ適用され、インターフェースのメソッドを再定義しないマーカーインターフェースは想像しやすい。そのようなマーカーインターフェースは、オブジェクト全体のある不変値(?)を記述したり、そのインスタンスは他の特定のクラスのメソッドによって処理されるように適合していることを指し示す(この意味では、Serializableインターフェースは、そのインスタンスがObjectOutputStreamに処理されることに適合していることを指し示している)。

マーカーアノテーションの利点は、大きなアノテーション機能の一部であるという点にある。それゆえ、マーカーアノテーションはアノテーションベースのフレームワークで一貫性が考慮されている。

マーカーアノテーション、マーカーインターフェースをどう使い分けるか?

まず、クラスとインターフェース以外の要素にマーカーをつけるには、マーカーアノテーションを使用するしかない。
クラス、インターフェースへのマーカーに関しては、
このマーキングをしたオブジェクトのみを対象としたメソッドを1つ以上書くことがあるか?
を考えてみる。
もし書くことがあるなら、マーカーインターフェースを利用するべき。これによって、メソッドの引数の型チェックをコンパイル時に行うことができる。
もし書かないのであれば、マーカーアノテーションを利用すべき。
アノテーションをたくさん使うフレームワークにおけるマーキングであれば、マーカーアノテーションを選ぶべき。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1