2013-08-26 10 views
7

これらの2つのクラスのジェネリックインターフェイスを作成したいと思いますが、ジェネリックを正しく指定する方法がわかりません。自分のクラスに制限されたジェネリックインターフェイスを作成する

public class ThingA implements Thing { 
    public ThingA createCopy(ThingA original); 
} 

public class ThingB implements Thing { 
    public ThingB createCopy(ThingB original); 
} 

私はこれを試しました。

public interface Thing<V extends Thing<V>> { 
    public V createCopy(V original); 

} 

しかし、私はまだこのようなことをすることができますが、これは許されるべきではありません。

public class ThingB implements Thing<ThingA> { 
    public ThingA createCopy(ThingA original); 
} 

答えて

6

thisキーワードジェネリックス(メソッドのパラメータと戻り値の宣言もありません)があり、あなたが望むものを正確に行うことはできません。

つまり、インターフェイスでは、クラス内のすべてのメソッドが一貫した型を使用することを許可しますが、型の型自体を参照することはできません。

0

あなたは

public interface Thing<V> { 
    public V createCopy(V original); 
} 

をお探しですか?そうでない場合は、「2つのクラスの汎用インターフェースを作成する」という意味をより詳しく説明できますか?

+1

これで彼は、彼が望んでいないものを正確に行うことができます。ジェネリックスは、ジェネリックスの目的とは全く反対の1つのタイプのクラスのみを使用することを妨げるものではありません。 – giorashc

1

これはできません。それはジェネリックスのためのものではありません。ジェネリックはタイプの安全のため、つまりキャストを避けます。誰かが何とかThing<ThingA>を実装するクラスThingBを作成すると、素晴らしいことです。これは完全な型セーフです。なんで気にするの?あなたは何をしているのですか?

0

あなたは、あなたがこのようことを行うことができ、実装の代わりに拡張子を自由に使用されている場合には:その後、

public interface Thing { ... } 
public abstract class Copyable { 
    public final Copyable copy() { 
     Copyable clone = createCopy(); 
     if (clone.getClass() != getClass()) 
      throw new RuntimeException("Copy has wrong type!"); 
     return clone; 
    } 
    protected abstract Copyable createCopy(); 
} 

など、それを使用します。これで

public class Test extends Copyable implements Thing { 
    public String content = null; 

    @Override 
    public Copyable createCopy() { 
     Test clone = new Test(); 
     clone.content = this.content; 
     return clone; 
    } 
} 

/*code somewhere*/ { 
    Test t1 = new Test(); 
    t1.content = "Hello world!"; 
    Test t2 = (Test)t1.copy(); 
    System.out.println(t2.content); 
} 

一つの問題は、ありますそのCopyableはインターフェイスではありません。しかし、これは例のように苦痛を伴うことなく使用できますが、使用されるクラスチェックは言語レベルではサポートされていません。言い換えれば、createCopy抽象メソッドは、それがコピーするクラスに限定されず、すべてそれはCopyableクラスを拡張するプログラマまたはそのクラスを拡張するクラスまでです。

肯定的な側面は、オブジェクト上で.copy()を呼び出すと、オブジェクト自体と同じオブジェクトを返す必要があるということです。例外の代わりに、nullを返すことができます。次に、が良いか何もないを得ました。

しかし、正直言って、私は実際にはあなたのcreateCopyローカルメソッドにパラメータがある理由を理解していません。 それは、静的メソッドである可能性が... altrough私もそのコードブロックに行くだろうか想像することはできません。

static <X extends Thing> X copy(X object) { ... } 

あなたは、静的な汎用的な方法でpraticeを組み合わせることができ、その結果は、もう少しフレンドリーになっ可能性があり:

public interface Thing extends Cloneable { 
    public static <X extends Thing> X copy(X thing) { 
     Object clone = thing.clone(); 
     if (clone.getClass() != getClass()) 
      throw new RuntimeException("Copy has wrong type!"); 
     return (X)clone; 
    } 
} 

public class ThingA implements Thing { 
    public Object clone() { ... } 
} 

/*code somewhere*/ { 
    ThingA a1 = new ThingA(); 
    ThingA a2 = Thing.copy(a1); 
} 

それでも、クローニング法ではなく、言語制限の例外によって規制が、私は、これははるかに最善の解決策だと思います。

関連する問題