3

「サービス プロバイダー」を開発しています (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 オブジェクトはクラスとインターフェースの両方を表しているようで、コンパイル時に実際にクラスまたはインターフェースであることを区別する方法はありません..

とにかく - すべてに感謝します。

4

3 に答える 3

0

2 番目の引数の代わりに、代わりにファクトリを渡すことができたらどうでしょうか。

interface IInterface{
    void go();
}

class IInterfaceImpl implements IInterface{
    public void go(){}
}

interface Factory<T>{
    T createInstance();
}

class FactoryImpl implements Factory<IInterface>{

    @Override
    public IInterface createInstance() {
        //you need to return an instance of IInterface, which can only be a class
        return new IInterfaceImpl();
    }
}
于 2013-04-17T09:48:46.250 に答える
0

クラスが具体的でインスタンス化可能なクラスであるかどうかは、次を使用して確認できます。

public boolean isConcrete(Class<?> input)
{
    if (input.isInterface())
         return false;

    if (Modifier.isAbstract(input.getModifiers()))
         return false;

    return true;
}
于 2013-04-17T09:30:50.227 に答える