「サービス プロバイダー」を開発しています (Google ジュースによく似ています)。その仕事は、任意の class_1 またはインターフェースをインスタンス化可能な*class_2* にマップし、class_1 (class_1 がインターフェースの場合) を実装するか、class_1 をis/extends (class_1 がインターフェースでない場合) にマップすることです。
だから現在私は方法を持っています
public <T> void map(Class<T> key, Class<? extends T> service)
コードの問題は、インターフェイス タイプを次のようにインターフェイス タイプにマッピングできることです。
ServiceProvider sp = new ServiceProvider();
sp.map(IParent.class, IChild.class);
これはエラーなしで完全にコンパイルされます (ICild は IParent を拡張します)。もちろん、後で、私がしたいとき:
IParent obj = sp.getService(IParent.class); //look for IParent mapping and instantiate the proper object
java.lang.InstantiationException を受け取りました。
質問は次のとおりです。
2 番目の引数が 1 番目の引数を実装または拡張するクラスであり、インターフェイスではないことをコンパイラがチェックするように、map() メソッドを宣言する方法は? (ポイントは、コンパイル時エラーを取得することです。実行時にこれをチェックする方法は既に知っています)
ありがとう。PS: はい。
UPD .: お時間をいただきありがとうございます。これが何であるかについて、もう少し言葉を加えてください。目標は、アプリケーションでの密結合やハードな依存関係を回避するのに役立つメカニズム (ServiceProvider クラス) を開発することです。そこで、私は次の哲学を開発/採用しました。software) -- すべてのパブリック インターフェイスを宣言します。実装はあなたの私的な仕事です。私たちはまったく気にしません。誰かがあなたのユニットを使用したい場合は、ServiceProvider に 1 でリクエストする必要があります。起動時に sp.map(IYuorInterface.class, TheClassImplementingIt.class); を使用します。2. IYuorInterface obj = sp.getService(IYuorInterface.class); TheClassImplementingIt クラスを「インスタンス化可能」にする責任があります (コンストラクター、セキュリティ、クラスが抽象化されていないなど)。そうでない場合 -- 実行時例外が発生してもまったく問題ありません。
メリットは何ですか?
これは非常に明白です。いつでも、他の開発者が IYuorInterface を再実装して ServiceProvider にマッピングすると、すべてのアプリケーションがコードを 1 行も変更することなくそれを使用できるようになります。(必要となる最も単純なケース -- 単体テスト)
したがって、私のポイント/質問は次のとおりです。 map() メソッドの2番目の引数は、インターフェイスではなくクラスを表すクラス型である必要があり、最初の引数と「互換性を割り当てる」必要があります。
つまり、 map(ISomeIterface.class, Something.class); を実行すると、何かのオブジェクト(インスタンス) は、次のように使用できる必要があります。
ISomeIterface obj = sp.getService(ISomeIterface.class);
//or in other words, just for example -- the Something can be used like this:
ISomeIterface obj = new Something();
これが、いくつかの回答で示唆されているように、ファクトリが受け入れられない理由です。ServiceProvider クラスはすでに一種の「ファクトリ」です。
..そして、Javaの Class オブジェクトはクラスとインターフェースの両方を表しているようで、コンパイル時に実際にクラスまたはインターフェースであることを区別する方法はありません..
とにかく - すべてに感謝します。