2014-10-01 115 views
-1

說我正在做一個實現接口的類的子類,並有這樣的代碼:不能實現抽象方法和抽象的說法

public void setGoalLocation(Location loc) 
{ 
    goal = loc; 
} 

的代碼無法編譯,因爲它要求我實現了一個「setGoalLocation(Ilocation loc)」方法,其中「Ilocation」是一個接口,「Location」是實現它的實際具體類。

這意味着我必須做這樣的事情:

public void setGoalLocation(ILocation loc) 
{ 
    goal = (Location)loc; 
} 

這只是似乎真的很尷尬。有趣的是,Java似乎並不關心返回Location的其他方法而不是接口ILocation。這工作:

public Location getStartLocation() 
{ 
    return start; 
} 

...即使 「需要」 的方法將是一個 「公共ILocation getStartLocation」。任何人都可以解釋爲什麼這樣,並且讓代碼變得不那麼笨拙嗎?我希望能夠使用位置作爲參數,而不是ILocation。

+1

請分享完整的類和接口定義。 – Aritra 2014-10-01 02:57:26

+0

這是正確的行爲。如果某些代碼僅通過接口與您的類進行通信,那麼代碼不會知道您的類只接受「位置」值。它期望你的類允許任何'ILocation'值。 – fluidsonic 2014-10-01 02:59:07

+0

關於返回值:通過接口與您的類進行通信的代碼需要任何'ILocation'返回值。由於'Location'匹配這個標準,所以使用它作爲更具體的返回類型是很好的。 – fluidsonic 2014-10-01 03:02:38

回答

1

的問題是,接口要求接受任何爲是ILocation一個亞型,而不僅僅是特定類型Location的對象參數的方法。如果您有另一種具體類型Position,它是ILocation的子類型,則實現該接口將要求您接受Position對象以及Location對象。

請注意,在您使用演員陣容的解決方法中,如果您碰巧通過Position而不是Location對象,則在運行時您會得到ClassCastException

由於設計問題,要解決這個問題,你可以定義接口的通用:

interface <T extends ILocation> TheInterface { 
    void setGoalLocation(T loc); 
} 

那麼你的具體類可以綁定的泛型參數:

public class MyClass implements TheInterface<Location> { 
    public void setGoalLocation(Location loc) { 
     . . . 
    } 
} 

至於返回類型,那是因爲任何Location對象是ILocation,因此當您返回Location時,您將返回ILocation

0

Java支持協變返回類型,其中子類(或接口實現)中方法的返回類型可以返回聲明類型的子類(或實現)。所以一般來說,以下是允許

public class A {} 

public class B extends A {} 

public class C { 
    A getSomething(); 
} 

public class D extends C { 
    B getSomething(); 
} 

如果接口有需要的接口類型的方法,你不能用不同的簽名覆蓋它。

public interface I { 
    void setSomething(ISomething somethingInterface); 
} 

你不能這樣做

public class Something implements ISomething {} 

public class MyI implements I { 
    void setSomething(Something somethingInterface); 
}