2013-12-23 63 views
2

我創建了兩個Java接口Tree<T>BinarySearchTree<T extends Comparable<T>>,其中第二個接口擴展了第一個接口。我有一個執行BinarySearchTree,稱爲LinkedBinarySearchTree。下面的代碼明顯抱怨在編譯時:在實現接口時擴展包含類型

Tree<Object> a = new LinkedBinarySearchTree<Object>(); 

因爲LinkedBinarySearchTree實現了已經指定TComparable類型的接口,並且Object s爲不Comparable。我完全理解這一點,並不構成我的實現問題。

我希望瞭解的是這種方法在實踐中是否會有危險。我無法想象這樣一種情況:從TreeBinarySearchTree的數據類型的「縮小」會給我一個運行時錯誤(ClassCastException,也許?),但我期待與更有知識的人員進行確認。從本質上來說,當擴展接口被認爲是不好的練習時,是「縮小」接口所持有的類型,如果是這樣,爲什麼?

+1

不,這不是一個壞習慣。你可以通過不縮小類型來使你的BST更通用,並且要求Comparator作爲參數,就像TreeSet一樣。 –

回答

1

事實上恰恰相反 - 這實際上是很好的做法。

請記住,使用泛型是一種通過在編譯時捕獲儘可能多的錯誤來避免編碼錯誤的技術。通過加強你的界面的特殊性,你實際上使人們更難以意外誤用它。不僅如此,他們的錯誤將在編譯時被發現。

1

這似乎並不是一件壞事。您是否得到ClassCastException取決於您試圖執行的操作,而不是實施方法。

「縮小」的一個常見情況是當人們想要專門化某些實現的類型時,從一個公共基礎派生。例如,每次執行一些計算器,具有不同的返回類型:

public interface Calculator<T> { 
    public Number calculate(T... arguments); 
} 

public interface NumberCalculator<T extends Number> extends Calculator<T> { 
    @Override 
    public T calculate(T... arguments); 
} 

public interface IntegerNumberCalculator extends NumberCalculator<Integer> { 
    @Override 
    public Integer calculate(Integer... arguments); 
} 

public interface FloatNumberCalculator extends NumberCalculator<Float> { 
    @Override 
    public Float calculate(Float... arguments); 
} 

上述參數可以指定被什麼東西給<T>不同,而返回類型可以繼續設置爲<T>爲每個子類中,從而提供更好的類型一致性,而不必一直返回一個對象Number