明确表示该类实现了接口

时间:2014-01-04 18:00:25

标签: java

在Java和类似语言中,必须明确表示类实现接口的真正原因是什么?

想象一下隐式实现:

interface Flyer { void fly(); }

public class Duck { public void fly() {...} }

public class Plane { public void fly() {...} }

public class Hoe { void hangAround() {...} }

void startFlying(Flyer flyer) {...}

void race() {
    ...
    startFlying(duck);  // OK
    startFlying(plane); // OK
    startFlying(hoe);   // Compilation error.
}

编译器知道方法的签名,返回类型(当然还有修饰符)。此时似乎很清楚,没有必要明确指定Duck和Plane实现Flyer。

我会说可以从Java中删除“实现XYZ”而不用担心。

没有区别,请在编译时检查,这样就可以了。

另一方面: @JBNizet提到了具有相同签名和返回类型的方法的不同含义。

我将使用他的例子:

interface Runner { void run(); }

public class Guy { public void run(); }
public class Gal { public void run(); }

void startRunning(Runner r) {...}

void race() {
    startRunning(guy);            // OK
    startRunning(gal);            // OK
    startRunning(runnableThread); // OK
}

确定编译器,确定startRunning()(对我来说没问题)。如果这对你好或没有,那取决于你的理念。

显式:

public class Guy **implements Runner **{ public void run(); }
public class Gal **implements Runner **{ public void run(); }

以粗体显示(或**和**之间的文字)是您必须支付的价格

void race() {
    startRunning(guy);            // OK
    startRunning(gal);            // OK
    startRunning(runnableThread); // Compilation error!
}

请注意编译错误,以便在测试之前查看问题。

如果它打算在startRunning()中使用runnableThread,你必须更明确地做到这一点(有足够的时间来实现你正在做的事情)。

“我想知道通过解决与隐式实现的接口问题浪费的时间相比,通过解决与键入”implements XYZ“相关的问题浪费了多少时间。如果对隐式实现的接口更好,那么我讨厌Java设计师决定,他们迫使我们相信它更好:-)“


瓢虫和空中客车(和鸭子)

我认为隐式实现界面的问题只是理论上的,实际上很少见。

public class Airbus {
    void takeOff() {...}
    void land() {...}
    Passenger[] getPassengers() {...}
}

public class Ladybug {
    void takeOff() {...}
    void land() {...}
}
public class Duck {
    void takeOff() {...}
    void land() {...}
    Passenger[] getPassengers() {...}
}

public interface Aircraft {
    void takeOff();
    void land();
    Passenger[] getPassengers();
}

public void fly(Aircraft aircraft) {
    aircraft.takeOff();
    for (Passenger p : aircraft.getPassengers()) {...}
    aircraft.land();
}

public void airport() {
    fly(airbus_a380); // OK
    fly(ladybug);     // Compilation error, does not match Aircraft requirements.
    fly(duck);        // OK
}

public interface Lander {
    void land();
}

public void landAtMeadow(Lander lander) {...}

public void meadow() {
    landAtMeadow(airbus_a380); // OK
    landAtMeadow(duck);        // OK
    landAtMeadow(ladybug);     // OK
}

所有这些都符合landAtMeadow的要求,因此可以在这种情况下使用它们。即使有可能无法在草地上降落airbus_a380(在其他方面需要测试),你需要在紧急情况下降落。

不要忘记landAtMeadow()可能有更具体的要求,如

public interface Lander { void landAtLimitedArea(int size); }

说空间有限,所以如果airbus_a380不支持这种方法,那么你在这里有编译错误。

4 个答案:

答案 0 :(得分:5)

Java是一种强类型语言,因此必须在编译时验证实例到接口类型变量的分配。这只能通过显式声明的接口实现来完成。

答案 1 :(得分:1)

正如其他人所说,这是Java语言的基本特征。这是有充分理由的,那些正在进行严肃的大规模编程的人,并且完全没有理由改变它。

如果它困扰你,我强烈建议您找到另一种类型较弱的语言并使用它。目前有相当多的语言可以编译成Java字节码并在Java环境中使用,因此您甚至不必放弃能够在JVM中运行的灵活性。

答案 2 :(得分:0)

我的朋友在强类型语言中,例如:在C或Java中,当声明变量或引用时,必须通知编译器变量或引用的数据类型

答案 3 :(得分:0)

当声明一个类实现接口X时,使用接口X 的任何其他方法都确保所有必要的方法都在类中实现(因此它们不需要每个都检查时间,如果需要的方法实施)。如果没有这样的声明,那么使用实现X的类的任何方法都需要:

  • 确保该方法正在工作的对象类实现了所有必要的方法(因此,每次期望使用接口X时,请仔细检查类的所有方法 - 而不是执行这一次,在汇编时。)

  • 有很多错误处理代码行实现(怎么做,如果我希望方法A做某事,但方法A根本不存在?)

静态类型通常会增加代码的安全性,因为在编译时可能会检测到许多错误。为什么要尝试将Java从staticaly更改为dynamicaly类型?有许多动态类型的语言,它们的优点和缺点,随时可用(例如Python)。