インタフェースの継承
ここ暫くは.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"の関係が無い以上、継承関係を作るのは正しくない。これももっともだ。
一体どちらを選択するのが良いだろう。