2013-02-02 12 views
15

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

インタフェース:

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) { 
     ... 
    } 

}  





は編集:

[OK]を、私は私が達成したいものを別の方法で記述してみてください。私はそのクラスの型のargを受け入れるメソッドを持ついくつかのクラスを持っていたいと思います。だから、さらに上からクラスAへのtheresの本のように見える別のクラス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); 

} 

をし、私はこのような別のインターフェイスに定義:プレイヤーが衝突を受けたとして、私のプレイヤーは、インタフェースICollisionReceiverを実装して、インスタンスのための今すぐ

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

    public void addCollisionReceiver(ICollisionReceiver<T> receiver); 

    public void removeCollisionReceiver(ICollisionReceiver<T> receiver); 

} 

をそれらを処理します。例えば、私はボックスと円を持っているので、これは、汎用的な方法で行う必要があり、今プレーヤーがICollisionReceiver <ボックス>とICollisionReceiverが実装<サークル> は私が持っている両方の方法

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

@Override 
public boolean collides(final Circle c) {   
    ... 
    return false; 
} 
私の箱とCircleクラスで

私は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()メソッドを呼び出します。

ここで重要なのは、ボックスとサークルの両方のクラスが独自の型でICollisionCheckerインターフェイスを実装していることを確認します。

私は明示的にこの

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

ような何かをすることによってこれを行うことができますが、これは私のために非常に満足ではありません...

長い記事のために申し訳ありませんが、私は、これは、それが明確に願っています。私はこれが助けを願ってい

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

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

:あなたが何をしたいか

+2

'public voidメソッド(Tオブジェクト);'はオプションではありませんか?私が正直であれば、私はあなたが達成したいことを理解していなかったからです。 – Zhedar

答えて

20

は、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) { 
    } 
} 

クラスを定義するならば、それが可能。なんで気にするの?何が問題なの?

+2

ハ、私はあなたが最初の文の後だったことを知っていた。常にCRTPを実行しようとしています:) –

+1

はいこれは一般的なジェネリックの意図ではないかもしれない制限ですが、1つのタイプだけがこの型自体。したがって、私はこれが可能であると思っていました。それにもかかわらず、あなたの答えは大変ありがとうございます。 – zersaegen

-1

は、おそらくこのようなものです!

+0

Javaが 'T 'が何であるかを知るためには、インタフェース宣言を' public interface MyInterface 'として指定する必要もあります。あなたの応答に感謝します。 – Michael

+1

残念ながら、ClassImplementingMyInterfaceをAではないクラスにすることができます。 – zersaegen

+0

実際にはこれは必要ありません。クラスのクラスではなくメソッドのジェネリックを宣言しました! – Pethor

4

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

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

あなたが見ることができるように、一般的な宣言はビット無限再帰のように見え、私はJavaの場合は型消去を持っていなかったことをかなり確信しています、それは次のようになります - ありがたいことに、あなたがこの

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

と予想されるなど

、この

を行うことができますので、コンパイラはそれらに対処した後、すべてのジェネリック医薬品が実際に Objectsあります(?)
public static void main(String[] args) { 
    Impl impl = new Impl(); 
    impl.method(impl); 
} 

何をしたいのプリントアウト

Hello! 
+2

脚注として、私はこれが完全に無意味であることがわかり、誰も実際にこれを使用することを推奨しません。 – Esko

+0

ありがとうが、私はまだこれを行うことができます:public class ImplBlubbはSelfImplementer を実装しているので、ImplBlubbはImplとのインターフェイスを実装します。私が欲しいのは、ImplBlubbがImplBlubbとのインターフェースを実装し、ImplがImplだけのインターフェースを実装できることです。 – zersaegen

+0

これは、OPが望むことをしません。あなたはまだ 'publicクラスSomeOtherImplを実装することができますSelfImplementer ' – newacct

関連する問題