明确表示该类实现了接口

Mar*_*lík 0 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.
}
Run Code Online (Sandbox Code Playgroud)

编译器知道方法的签名,返回类型(当然还有修饰符).在这一点上,似乎很清楚,没有必要明确指定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
}
Run Code Online (Sandbox Code Playgroud)

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

明确:

public class Guy **implements Runner **{ public void run(); }
public class Gal **implements Runner **{ public void run(); }
Run Code Online (Sandbox Code Playgroud)

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

void race() {
    startRunning(guy);            // OK
    startRunning(gal);            // OK
    startRunning(runnableThread); // Compilation error!
}
Run Code Online (Sandbox Code Playgroud)

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

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

"我想知道通过解决与隐式实现的接口问题浪费的时间相比,通过解决与输入"实现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
}
Run Code Online (Sandbox Code Playgroud)

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

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

public interface Lander { void landAtLimitedArea(int size); }
Run Code Online (Sandbox Code Playgroud)

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

And*_*res 5

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