29

Javaで、実装クラスの引数を受け取るメソッドを持つインターフェースを定義することはできますか?

インターフェース:

public interface MyInterface {
   public <T is/extends of the type of the implementing class> void method(T object);
}

クラス:

public class A implements MyInterface {

    public void method(A object) {
       ...
    }

}

私が避けたいのは、クラスがそれ自体のような別のクラスで MyInterface を実装できることです。

したがって、これは許可されるべきではありません:

public class A implements MyInterface<B> {

    public void method(B object) {
       ...
    }

}    





編集:

わかりました、私が達成したいことを別の方法で説明しようとします。そのタイプのクラスの引数を受け入れるメソッドを持ついくつかのクラスが必要です。したがって、上記のクラス A に加えて、次のような別のクラス B があるとします。

public class B implements MyInterface {

    public void method(B object) {
       ...
    }

}

ブース クラス A と B に共通するのは、クラス自体の型の引数を受け取る「メソッド」と呼ばれるメソッドです。

私のプロジェクトでは、次のことを達成したいと考えています。私は小さなゲームを書いており、ある種の衝突検出を実装したいと考えています。基本的に、「スマートな」ポリモーフィスティック呼び出しを行うことでこれを行いたいと考えています。

次のようなインターフェイス ICollisionReceiver を定義しました。

public interface ICollisionReceiver<T extends IShape> extends IShape {

    public boolean collides(T t);

}

そして、次のような別のインターフェースを定義しました:

public interface ICollisionChecker<T extends ICollisionChecker<T>> extends IShape {

    public void addCollisionReceiver(ICollisionReceiver<T> receiver);

    public void removeCollisionReceiver(ICollisionReceiver<T> receiver);

}

たとえば、私のプレーヤーは、衝突を受け取って処理するときに ICollisionReceiver インターフェイスを実装します。これは一般的な方法で行う必要があるため、たとえば、ボックスとサークルがあり、Player は ICollisionReceiver < Box > と ICollisionReceiver < Circle > を実装しているため、両方のメソッドがあります。

@Override
public boolean collides(final Box b) {        
    ...
    return false;
}

@Override
public boolean collides(final Circle c) {        
    ...
    return false;
}

私のボックスとサークル クラスでは、ICollisionReceivers を登録できます。次に、update メソッドで次のことを行います。

    boolean conti = true;
    int i=0;
    while(conti && i<collisionReceivers.size()) {
        final ICollisionReceiver<Bonus> rec = collisionReceivers.get(i);               
        if(this.collidesWith(rec)) {
            conti = rec.collides(this);
        }            
        ++i;
    }

これは基本的に、このボックスが特定のレシーバーと衝突するかどうかをチェックし、レシーバーのcollides()メソッドを呼び出します。

要点は、クラス box と circle の両方が ICollisionChecker インターフェイスを独自の型でのみ実装することを確認したいということです。

このようなことを行うことで、明示的にこれを行うことができます

public class Bonus extends AnimatedSprite implements ICollisionChecker<Bonus>...

しかし、これは私にとって非常に満足のいくものではありません...

長い投稿で申し訳ありませんが、これで明確になることを願っています。

4

3 に答える 3

38

あなたが望むことはJavaでは不可能であり、役に立ちません。

したがって、これは許可されるべきではありません:

なぜだめですか?それはどのような目的に役立ちますか?ジェネリックは、恣意的な制限を行うためのものではありません。ジェネリクスは、キャストが常に安全であることを証明できるため、そうでなければ必要なキャストを排除する場合にのみ役立ちます。

タイプセーフである限り、public class A implements MyInterface<B>それを禁止する任意の制限を加えても意味がありません。

インターフェイスを次のように定義するだけです。

public interface MyInterface<T> {
   public void method(T object);
}

クラスを定義できます

public class A implements MyInterface<A> {
    public void method(A object) {
    }
}

他の誰かがクラスを定義した場合

public class B implements MyInterface<A> {
    public void method(A object) {
    }
}

それならそうです。なんで気にするの?それはどのような問題を引き起こしますか?

于 2013-02-03T00:43:33.103 に答える
5

まあ、これは少なくとも可能です:

public interface SelfImplementer<T extends SelfImplementer<T>> {
    void method(T self);
}

ご覧のとおり、Generic 宣言は無限再帰に少し似ています。Java に型消去がなかったら、ありがたいことに (?) すべてのジェネリックは実際Objectsにはコンパイラがそれらを処理した後であると確信しています。これを行うことができます

public class Impl implements SelfImplementer<Impl> {
    @Override
    public void method(Impl self) {
        System.out.println("Hello!");
    }
}

そして予想通りこれは

public static void main(String[] args) {
    Impl impl = new Impl();
    impl.method(impl);
}

プリントアウト

Hello!
于 2013-02-02T20:17:34.357 に答える
-1

あなたがやりたいことは、おそらく次のようなものです:

public interface MyInterface <T extends A> {
    public void method(T object) {
        ...
    }
}

public class A implements MyInterface<A_or_class_extending_A>
{ ... }

これが役に立ったことを願っています!

于 2013-02-02T19:25:39.613 に答える