APIを進化させようとしています。この進化の一環として、高度なクライアントが新しい機能にアクセスできるようにするには、メソッドの戻り型をサブクラス(特殊化)に変更する必要があります。例(醜いものは無視してください:
public interface Entity {
boolean a();
}
public interface Intf1 {
Entity entity();
}
public interface Main {
Intf1 intf();
}
私は今、次のようにExtendedEntity、Intf2、およびMainを使用したいと考えています。
public interface ExtendedEntity extends Entity {
boolean b();
}
public interface Intf2 extends Intf1 {
ExtendedEntity entity();
}
public interface Main {
Intf2 intf();
}
ただし、メソッドの戻り型はそのシグネチャの一部であるため、以前のバージョンのコードですでにコンパイルされているクライアントは、リンケージエラーを示します(メソッドがiircで見つかりません)。
私がやりたいのは、別の戻りタイプを持つメソッドをMainに追加することです。2つのメソッド(1つはスーパータイプを返し、もう1つはサブタイプを返す)は、同じ実装メソッド(サブタイプを返す)にマップする必要があります。注-私が理解している限り、これはJVMで許可されていますが、Java仕様では許可されていません。
私の解決策は、必要なインターフェースを追加するためにJavaクラスシステムを悪用しているようです(私はそれについて他の言葉はありません)。
public interface Main_Backward_Compatible {
Intf1 intf();
}
public interface Main extends Main_Backward_Compatible{
Intf2 intf();
}
これで、古いクライアントは正しいメソッドをinvokevirtualルックアップに返します(正しいリターンタイプのメソッドがタイプ階層に存在するため)。実際に機能する実装は、サブタイプIntf2を返す実装になります。
これはうまくいくようです。私が考案できたすべてのテストで(リフレクションを除いて-しかし、私はそのビットについては気にしません)、それは機能しました。
それは常に機能しますか?私の推論(invokevirtualについて)は正しいですか?
そして、別の関連する質問-「実際の」バイナリ互換性をチェックするためのツールはありますか?私が見つけた唯一のものは、それ自体で各メソッドを調べますが、タイプ階層を考慮していません。
ありがとう、
蘭。
編集-私が試したツールで「あまり良くない」ことがわかりました(タイプ階層を考慮しないでください):
- Clirr0.6。
- IntelliJ「APIComparator」プラグイン。
Edit2-もちろん、私のクライアントは私のインターフェースへの実装クラスを作成することを禁じられています(サービスを考えてください)。ただし、例を完全なものにしたい場合は、インターフェイスではなく抽象クラス(Main用)を検討してください。