Java 无法使用抽象参数的子类实现抽象方法

Java 无法使用抽象参数的子类实现抽象方法,java,interface,Java,Interface,假设我正在创建一个实现接口的类,其代码如下: public void setGoalLocation(Location loc) { goal = loc; } public void setGoalLocation(ILocation loc) { goal = (Location)loc; } 代码没有编译,因为它要求我实现一个“setGoalLocation(Ilocation loc)”方法,其中“Ilocation”是一个接口,“Location”是实现它的实际具体

假设我正在创建一个实现接口的类,其代码如下:

public void setGoalLocation(Location loc)
{
    goal = loc;
}
public void setGoalLocation(ILocation loc)
{
    goal = (Location)loc;
}
代码没有编译,因为它要求我实现一个“setGoalLocation(Ilocation loc)”方法,其中“Ilocation”是一个接口,“Location”是实现它的实际具体类

这意味着我必须这样做:

public void setGoalLocation(Location loc)
{
    goal = loc;
}
public void setGoalLocation(ILocation loc)
{
    goal = (Location)loc;
}
这看起来真的很尴尬。有趣的是,Java似乎并不关心其他方法返回位置,而不是接口ILocation。这项工作:

public Location getStartLocation()
{
    return start;
}

…即使“必需”方法是“publicILocationgetStartLocation”。有人能解释为什么会这样,以及有什么帮助可以让代码不那么尴尬吗?我希望能够使用位置作为参数,而不是ILocation。

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);
}

问题是接口需要一个方法,该方法接受任何作为
ILocation
子类型的参数,而不仅仅是特定类型
位置的对象。如果您有另一个具体类型
Position
,它是
ILocation
的子类型,那么实现该接口将要求您接受
位置
对象以及
位置
对象

请注意,在使用cast的工作中,如果您碰巧传递了
位置而不是
位置
对象,则在运行时会得到一个
ClassCastException

作为一个设计问题,要解决这个问题,您可以将您的接口定义为通用接口:

interface <T extends ILocation> TheInterface {
    void setGoalLocation(T loc);
}
接口接口{
无效设置分配(T loc);
}
然后,您的具体类可以绑定泛型参数:

public class MyClass implements TheInterface<Location> {
    public void setGoalLocation(Location loc) {
        . . .
    }
}
公共类MyClass实现接口{
公共作废设置分配(位置loc){
. . .
}
}

至于返回类型,这是因为任何
Location
对象都是
ILocation
,因此当您返回
Location
时,您返回的是
ILocation

请共享完整的类和接口定义。这是正确的行为。如果某些代码仅通过接口与您的类通信,那么代码不知道您的类只接受一个
位置
值。它期望类允许任何
ILocation
值。关于返回值:通过接口与类通信的代码期望任何
ILocation
返回值。由于
Location
符合此标准,因此将其用作更具体的返回类型是可以的。