2013-10-07 47 views
0

我有一個名爲BST(簡稱二叉搜索樹)的Java接口,它具有泛型類型鍵,值其中鍵擴展Comparable.I定義如下。實現一個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(); 

} 

現在我想implements BST<Key似乎後是定義試過這種

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

... 

} 

上述定義引起的Eclipse IDE ..The extends標記的錯誤消息,上述interface.I的實現罪魁禍首

令牌

語法錯誤 「擴展」,預計

如果我省略了自定義「擴展」標誌(如下給出),錯誤消失了,我可以得到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; 
    } 
} 

爲什麼在擴展標記原因的錯誤在第一位?有人可以解釋嗎?

+2

你不需要重複「重點延伸什麼都不是「每次。只有當你引入一個類型變量時纔會這樣做。 – Ingo

回答

5

因爲

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

在你的類聲明中,泛型類型爲類型聲明,東西,你可以在類體內之後重用。在你正在實現的接口中,它是一個類型參數參數。換句話說,你說我的類用這種類型實現了這個接口。你必須給它一個特定的類型。將Key extends Comparable...作爲類型參數說明沒有意義。

Java Language Spec has more details

type參數部遵循類名,由 角括號分隔。

the section for Superclasses

如果TypeDeclSpecifier之後通過任何類型的參數,它必須是 由 TypeDeclSpecifier表示的類型聲明的正確調用,並且沒有一個類型的參數可以是通配符鍵入 參數,或發生編譯時錯誤。

+1

這是一個令人遺憾的使用和聲明混淆共享語法。 –

+0

@ TomHawtin-tackline請注意,他們在C#中也是這樣做的,並且可以用C++來說明(尖括號會在其他地方出現)。實際上,相關語言功能具有相同的語法很常見。但是,C#通過將**約束**放在尖括號之外來整齊地解決這個問題,而不必使用不同的語法來使用和聲明。 – millimoose

+0

@millimoose這是一個至少可以回溯到C的哲學。預先ANSI類型沒有出現在函數聲明中的參數旁邊 - 稍後有重複的參數名稱(錯誤被C++/C With類構造函數)。因爲使用和聲明有不同的需求,所以可以避免混淆。 –

1

其他答案是正確的,但我只是想補充修復

基本上,你傳遞的類型參數到超/接口,如:

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

也請遵循Java命名標準和使用單字母的泛型參數辣妹。使用單詞很容易與作爲類名稱混淆。

1

關鍵字extendssuper定義約束條件關於泛型類型。只限制中的類型參數是有意義的,而不是類型參數爲out

這種情況類似於方法參數。在聲明的方法,你可以使用:

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

(在「約束」是傳遞給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

(這種對稱性也說明了什麼仿製藥真的是:他們是高階類型約束,即指定「類型的類型」的方式)