我对Java类实现的抽象方法签名感到很困惑。
例如,考虑:
interface Programmer {
Object program();
}
class Linus implements Programmer {
public String program() {
return "goto end;";
}
}
public class Main {
public static void main(String[] args) {
System.out.println(new Linus().program());
}
}
这显然是可以接受的,因为任何期望来自Linus.program()的Object都会得到一个(特别是一个字符串)。
但现在考虑一下:
interface OS {
void run(String code);
}
class Linux implements OS {
public void run(Object code) {
System.out.println("Hello world");
}
}
public class Main {
public static void main(String[] args) {
new Linux().run("print 'Hello world'");
}
}
这无法编译,并产生错误:
The type Linux must implement the inherited abstract method OS.run(String)
现在,任何事情都可以预期能够将一个String传递到OS界面的任何实例中,你当然可以用Linux做到这一点。
我认为没有理由为什么第二个无法编译。在Java编译第二个程序的后果中,我是否遗漏了令这个禁令的内容?
答案 0 :(得分:5)
您在第二种情况下所做的是方法过载
方法的签名是“方法名称”和“参数的数量和类型”
在第二种情况下,您正在更改编译器事物是另一种方法的参数类型,并要求您实现抽象(未实现)方法。如果您实现接口public void run(String code)
中存在的方法,则此方法public void run(Object code)
将被视为重载方法。
注意:方法覆盖永远不会基于方法的返回类型。由于返回类型不被视为方法的签名
答案 1 :(得分:0)
您不能传递基类Object的实例来代替类String的实例,但反向有效。在您的接口OS中,run方法的参数是String类型,在实现类中,您将参数概括为Object类型,这是不允许的。因此,编译器会抱怨。
答案 2 :(得分:0)
你说“现在,任何事情都可以预期能够将一个字符串传递给操作系统界面的任何实例,你肯定可以用Linux做到这一点。” =>问题是你可以,但不是必须的。
考虑一下:因为该方法的Linux版本将Object作为参数,您可以尝试传递Collection,例如。因此,您不会尊重接口,它明确地将参数限制为String。这就是为什么Linux版本的方法不被认为是操作系统版本的“孩子”。
由于接口中的每个方法都需要有“子”,编译器会抱怨你没有为OS.run(String)实现“子”