2016-09-15 11 views
0

型パラメータについて混乱しています。次のコードでは、CollectionDataの角括弧内の型を型パラメータと呼ぶことができます。 ArrayListとGenerator内の型は型パラメータではなく、CollectionDataで同じである必要があります。それを理解する方法?型パラメータを正しく使用する方法

//correct 
public class CollectionData<T> extends ArrayList<T> { 
    CollectionData(Generator<T> generator) { 

    } 
} 

interface Generator<E> { 
    E next(); 
} 

以下は間違っています。しかし、私はこれを書くのを手助けすることはできません。

// wrong 
public class CollectionData<T> extends ArrayList<E> { 
    CollectionData(Generator<W> generator) { 

    } 
} 

interface Generator<E> { 
    E next(); 
} 

追加さ
上記の例では、唯一のかなりのArrayListまたは発電機よりも、CollectionDataの山括弧で定義されている変数を入力することができますか? ArrayListとCollectionDataは、これらの型を使用します。右?

+3

「次は間違っています」必ずしも状況に左右されません。型変数 'E'と' W'が定義されているスコープに書いたのであれば、それは(例えばネストされたクラスとして)動作します。しかし、私はこれを書くのを手伝うことはできません。どうして?どういう意味ですか? –

+0

@Andy Turner ArrayListが型パラメータ 'E'を定義すると思います。 – Hel

答えて

3

これらの汎用タイプは、タイプの変数です。

public class CollectionData<T> extends ArrayList<E> { 

を書く

には、変数yが存在しない場合、このコードが間違っている

public int func(int x) { 
    return y; 
} 

を書くことに似ています。 あなたがxを宣言したので、しかし、あなたは適切なx使用することができます。

public int func(int x) { 
    return x; 
} 

同じことが、一般的なタイプのために真であるが。あなたは

public class CollectionData<T> extends ArrayList<T> 

を書くとき あなたのクラスにジェネリック型引数で与えられたようArrayList<T>内部Tが同一Tであると言っています。 コンストラクタのパラメータ型も同じです。

"正しい"コードを書くタイミングを知る手助けをする:両方のジェネリックタイプが同じである必要がある場合(例えば、クラスに与えられたジェネリックタイプとベースクラスのジェネリックタイプ、引数)を使用する場合、同じ型変数を使用する必要があります。 これは、その変数に格納されている正確な値が必要な場合に、関数内で同じ変数を使用するのと同じです。あなたの補遺のため


編集:

ジェネリック型が唯一のクラス名を宣言することができます。

public class CollectionData<T> extends ArrayList<E> 

Tを宣言しますが、唯一のEを使用しています。これはもちろん、Eがどこかでジェネリック型(または事実上のクラス)として宣言されていることを必要とします。 (Eがジェネリック型の場合、CollectionData<T>Eを宣言する外側のクラスの内側にある場合のみ有効です。もちろん)

、ジェネリック型はまた、すべての機能のために宣言することができます。

public <T> void foo(T x) { x.baz(); } 

このTTのいずれかの定義を宣言します。例えば は、この文脈で

public class Foo<T> { 
    public <T> void foo(T x) { x.baz(); } 
} 

foo方法内側TクラスFooによって宣言Tありません。 この作品-再びのようなシャドウイング変数:

public class Foo { 
    int x; 
    public int foo(int x) { 
     // returns x from argument, not the field of the class 
     return x; 
    } 
} 
1

私はあなたが渡されたGeneratorにより、コンストラクタ内のコンテンツであなたのCollectionDataインスタンスを埋めようとしていることを前提としています。

一致が必要な場合は、同じタイプパラメータを使用する必要があります。最初の例では、CollectionDataの型パラメータはすべてTです。同じ識別子を持つため、コンパイラは一致する必要があることを認識します。

2番目の例では、パラメータT,WおよびEが入力されています。 EまたはTのリストを必ず入力してというインスタンスにすることはできないため、これは機能しません。コンパイラは、インスタンス型が互換性があることを知る方法がありません。

1

私はあなたのconfisionを引き起こしているものだと思うが 1を使用して定義ジェネリック型ととの間の差です。

を定義するジェネリック型は基本的には関数の定義に似ています。つまり、パラメーターとそのパラメーターの使用方法を定義します。

を使用すると、汎用型とはコンパイラが完全に理解できなければならないことを意味します。これは定義済みの型に依存することはできません。

この例では、定義は単語extendsで終了します。後続のすべてがジェネリック型を使用しているため、定義ヘッダーの型パラメーターを除いて、未知の型は使用できません。関数定義と同様に、混乱を解消するのに役立ちます。

関連する問題