インタフェースの継承
ここ暫くは.NET2.0ネタに終始してたし、正直疲れたので、今日は久しぶりにまったりとできるネタ。
次のようなインタフェースがあるとする
public interface FieldAccessible { string getFieldA(); void setFieldA(string fieldA); string getFieldB(); void setFieldB(string fieldB); string getFieldC(); void setFieldC(string fieldC); }
このインタフェースを使用してJavaでシステムの開発を開始したが、開発が終盤に差しかかろうという時期に、今度は以下のようなインタフェースが必要になったとする。
public interface FieldAccessible2 { string getFieldB(); void setFieldB(string fieldB); string getFieldC(); void setFieldC(string fieldC); string getFieldD(); void setFieldD(string fieldD); string getFieldE(); void setFieldD(string fieldE); }
FieldAccessibleとFieldAccessible2は似ているが同じでは無い。実は、これらの二つのインタフェースは元々レガシーなシステムから切り出したデータ構造であり、内部ではC言語の共用体で定義していたデータ構造だった経緯がある。なのでフィールド"B"とフィールド"C"は共通だが、互いに共通では無いフィールドも持っている。
この時、互いのインタフェースの関係をどのように設計するのが良いのだろう。
1.インタフェースの継承関係を作る
元々は共有していたデータ構造なのだから、FieldAccessibleとFieldAccessible2は同種のデータである、と考える。従ってインタフェースも継承しているように設計するべきだ。
まずは、共通のフィールドを括り出してルートのインタフェースを設計し
public interface FieldAccessible { string getFieldB(); void setFieldB(string fieldB); string getFieldC(); void setFieldC(string fieldC); }
その後、差分を継承したインタフェースとして定義する。
public interface FieldAccessible1 extends FieldAccessible { string getFieldA(); void setFieldA(string fieldA); }
public interface FieldAccessible2 extends FieldAccessible { string getFieldD(); void setFieldD(string fieldD); string getFieldE(); void setFieldD(string fieldE); }
2. 互いに別なインタフェースとして継承関係は作らない
元々はCの共有体を使用していたとはいえ、似て非なるデータ構造であり"FieldAccessible is FieldAccessible2"の関係は成り立たない。従って、継承関係は作らず、互いに別なインタフェースのまま定義する。
このような場合、私ならば前者(継承関係を作る)を選択する。"is a"の関係が無いと解っていても、だ。実装にはTemplateパータンを用いてFieldAccessibleインタフェースの実装には抽象クラスを用いるだろう。しかし、元々C言語で共用体で使用していただけの2つのデータ構造の間に"is a"の関係を持ち出すのはどうか、という意見もある。"is a"の関係が無い以上、継承関係を作るのは正しくない。これももっともだ。
一体どちらを選択するのが良いだろう。