2011-08-18 49 views
4

我有這樣的結構:Java泛型,爲什麼在泛型中使用繼承是非法的?

///Creep.java/// 
public interface Creep extends Movable<Position2D> { 
    ... 
} 


///Movable.java/// 
public interface Movable<T extends Position2D> { 
     ... 
    void setMovementStrategy(MovementStrategy<Movable<T>> movementStrategy); 
    MovementStrategy<Movable<T>> getMovementStrategy(); 
} 


///MovementStrategy.java/// 
public interface MovementStrategy<T extends Movable<? extends Position2D>> { 
    void executeMovement(T movable); 
} 


///CreepImpl.java/// 
public class CreepImpl implements Creep { 
... 

@Override 
public void setMovementStrategy(MovementStrategy<Creep> movementStrategy) { 
    // TODO Auto-generated method stub 

} 

@Override 
public MovementStrategy<Creep> getMovementStrategy() { 
    return null; 
} 

} 

我的問題是仿製藥不喜歡MovementStrategy<Creep>但它確實接受MovementStrategy<Movable<Position2D>>我認爲這是奇怪的Creep擴展Movable<Position2D>。這在方法的背景下public MovementStrategy<Creep> getMovementStrategy()public MovementStrategy<Creep> getMovementStrategy()

這不可能嗎?或者也許我做錯了什麼?

任何幫助表示讚賞!

編輯

忘了包括MovementStrategy源..衛生署!

+0

究竟什麼是你得到的錯誤,並在代碼行? –

+0

那麼,沒有錯誤,更多的日食警告和紅色的下劃線:)。我的問題更多的是爲什麼當'Creep'是一個更具體的類型'Movable ' – netbrain

+1

btw時,爲什麼'MovementStrategy >'等於'MovementStrategy ',MovementStrategy不應該是通用的。它總是適用於Movable對象, – Bozho

回答

10

也許你甚至不需要仿製藥與MovementStrategy。儘量不要創造那麼多的泛型複雜性。


原來的答覆:你可以使用關鍵字extendsMovementStrategy<? extends Movable>

這需要保存編譯時的安全性。

設想以下是可能的:Creep extends MovableWind extends Movable

MovementStrategy<Movable> strategy = new MovementStrategy<Wind>(); 
strategy.setTargetObject(new Creep()); //fails 

像第二屆無法在運行,因爲它需要風,但你給它一個蠕變

+0

但爲什麼呢?編譯器需要什麼「擴展Creep」而不是簡單地「蠕變」? – Heisenbug

+1

保留編譯時安全性。我將添加一個解釋 – Bozho

+0

MovementStrategy是一個接口,定義如下'public interface MovementStrategy >'將T改爲?正如您在IDE警告/錯誤中建議的結果。 – netbrain

2

把這個示例代碼:

Movable<Position2D> moveable = new CreepImpl(); 
MovementStrategy<Movable<Position2D>> strategy=/*some strategy here */; 
moveable.setMovementStrategy(strategy); 

因爲CreepImpl只接受MovementStrategy<Creep>,最後一行應該失敗,儘管它是完全合法的,這意味着CreepImpl不是Moveable<Position2D>的有效替代者

在Java中,當B擴展或實現A時,B類型的每個對象也可以分配給A類型的變量,並且B不會引入任何約束來限制A.

+0

謝謝,你給了我一個「aha」時刻;) – netbrain

1

多態性不適用於像數組這樣的泛型。

JVM在運行時不知道對象的類型,這稱爲類型擦除,並且是爲了逆向兼容而完成的。 只有編譯器知道實例的類型。

泛型設計大多爲集合......這件事是你必須知道,它可以插入一個字符串列表,如果傳遞的整數的方法爲例的ArrayList採取列表

試用一下下面的代碼,這將令你感到驚訝:

public static void main(String[] args) { 
    Set<Integer> set = new HashSet<Integer>(); 
    for (int i=0 ; i<10 ; i++) { 
     set.add(i); 
    } 
    methode(set); 
    for (Integer i : set) { 
     System.out.println(i); 
    } 
} 
public static void methode(Set set) { 
    set.add("test"); 
} 

它編譯,運行,甚至引發例外前給予一定的數字!

現在讓我們看下面的代碼:

public static void main(String[] args) { 
    Set<Integer> set = new HashSet<Integer>(); 
    for (int i=0 ; i<10 ; i++) { 
     set.add(i); 
    } 
    methode(set); // NOK 
    for (Integer i : set) { 
     System.out.println(i); 
    } 
} 
public static void methode(Set<Number> set) { 
    set.add(3f); 
} 

這幾乎是同樣在這裏,如果多態性是確定與仿製藥,你可以是一個整數集傳遞給需要一組數字的方法,然後添加一個float到整數集合!

太陽設計的仿製藥,這樣,如果你不使用傳統的非類型化的代碼,你的收藏品保持爲類型安全的...

像Bozho說,在我爲例,你可以作爲參數使用

Set<? extends Number> 

,因此可以將一組整數傳遞給該方法。 我不記得確切,但在這種情況下,我認爲Java給你上插入一個新的項目到該列表的危險警告...

+0

請注意,對於數組,數組的類型在運行時是已知的,所以如果你嘗試向數組添加一個錯誤的值,你會得到一個ArrayStoreException,而與集合,你可以添加一個浮動,並且你將得到的錯誤可能是一個ClassCastException,而迭代列表 –

1

您的問題是蠕變實現接口Movable<Position2D>,並Movable<Position2D>期待方法setMovementStrategy(MovementStrategy<Movable<Position2D>> movementStrategy)MovementStrategy<Movable<T>> getMovementStrategy()

看看這個簡單的非通用例如:

public interface iTest() { 
    doSomething(Object o); 
} 

public class Test implements iTest { 
    @Overide 
    doSomething(Test t) { 
    //error 
    } 
} 

正如你所看到的,doSomething(Test t)只實現iTest接口的一小部分。如果有人寫folling代碼,存在Test沒有方法來執行它:

public class TestImpl { 
    public static void main(String[] args) { 
    iTest t = new Test(); 
    t.doSomething("Hi"); // valid, because iTest.doSomething() expects a Object, and String is a Object. 
    Test t2 = new Test(); 
    t2.doSomething("Hi"); // invalid, Test does not have a doSomething(String). 
    } 
} 
+0

是的,我通過刪除不需要的泛型來解決它。但是謝謝! – netbrain