0

私は BST (二分探索木の略) と呼ばれる Java インターフェースを持っています。

public interface BST<Key extends Comparable<Key>,Value> {

    public void put(Key key,Value value);

    public Value get(Key key);

    public void delete(Key key);

    public Iterable<Key> keys();

}

今、上記のインターフェースの実装を定義したいと思います。私はこれを試しました

public class BSTImpl<Key extends Comparable<Key> ,Value>  implements BST<Key extends Comparable<Key>,Value> {

... 

}

上記の定義により、Eclipse IDE でエラー メッセージが表示され ます。extends後のトークンが原因のimplements BST<Keyようです。

トークン「extends」の構文エラー、予想

定義から「extends」トークンを省略すると (以下に示すように)、エラーはなくなり、Eclipse で未実装のメソッドを正しく生成できます。

public class BSTImpl<Key extends Comparable<Key> ,Value>  implements BST<Key ,Value> {
    @Override
    public void put(Key key, Value value) {
        // TODO Auto-generated method stub          
    }
    @Override
    public Value get(Key key) {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public void delete(Key key) {
        // TODO Auto-generated method stub          
    }
    @Override
    public Iterable<Key> keys() {
        // TODO Auto-generated method stub
        return null;
    }
}

そもそもなぜ extends トークンでエラーが発生するのでしょうか? 誰か説明してもらえますか?

4

3 に答える 3

5

なぜなら

public class BSTImpl<Key extends Comparable<Key> ,Value>  implements BST<Key extends Comparable<Key>,Value> {
                    ^ type declaration                                   ^ type argument

クラス宣言では、ジェネリック型は型宣言であり、後でクラス本体で再利用できます。実装しているインターフェイスでは、これは型引数引数です。言い換えれば、私のクラスはこの型でこのインターフェースを実装していると言っています。特定のタイプを指定する必要があります。Key extends Comparable...型引数として言っても意味がありません。

Java 言語仕様に詳細があります

型パラメーター セクションはクラス名の後に続き、山かっこで区切られます。

およびスーパークラスのセクション

TypeDeclSpecifier の後に任意の型引数が続く場合、それは TypeDeclSpecifier によって示される型宣言の正しい呼び出しである必要があり、型引数のいずれもワイルドカード型引数である必要はなく、コンパイル時エラーが発生します。

于 2013-10-07T16:04:44.463 に答える
1

キーワードextendsとジェネリック型の制約superを定義します。て行く型パラメータではなく、入ってくる型パラメータを制限するだけで意味があります。

この状況は、メソッドのパラメーターに似ています。メソッドを宣言するときは、次を使用します。

public void foo(Bar bar) { 
    //          ^ the type is a constraint on bar 
}

(「制約」とは、渡される値がまたはそのサブタイプの 1 つでbarなければならないということです。)Bar

ただし、次のようにメソッドを呼び出します。

foo(someBar);
//  ^ no constraint specified here

つまり、変数が使用されている場所で変数の型を制限しても意味がありません。(それはすでに宣言で行われています。)

クラス宣言では、ジェネリック型が宣言されており、別の型が同じ行で使用されているため、さらに混乱します。その行の解釈は次のとおりです。

class BSTImpl<Key extends Comparable<Key>, Value>
//                ^ a constraint on the types that can be passed to Key
    implements BST<Key, Value>
//                 ^ here we're passing Key to another generic type

もちろん、変数の場合と同様に、 の着信「タイプ」はKey、それが使用される場所で必要なタイプと互換性がある必要があります。そのため、 の宣言で制約を複製する必要がありBSTImplます。

(この対称性は、ジェネリックが実際に何であるかを示しています。ジェネリックは高次の型制約であり、「型の型」を指定する方法です。)

于 2013-10-07T16:20:14.290 に答える