我一直在努力学习Java并试图真正理解它以及它是如何工作的。我能够理解界面是什么(或者我认为)。我也看过他们的一些例子......但我还没有能够理解一些接口是如何实现的,并且它们已经具有某种功能......不是。你应该在每次实现该方法时编写该功能吗?
举一些例子,有一个LibGDX,一个非常着名的Java游戏开发库。您的应用程序类必须实现一个具有" render()"等方法的接口。编写应用程序时,将所有与渲染相关的内容放在" render()"方法......但它如何知道如何处理它,如果它只是一个只定义render()的名称和返回类型的接口?
对不起我的英文,谢谢。
编辑:谢谢你的回答,是的,我在这方面有点新......我很困惑,你真的很有帮助!。答案 0 :(得分:1)
使用您的示例,当您的类实现接口时,框架知道您的类的实例具有render()
方法,因此框架可以在需要时调用它。
框架不需要知道(或关心)该实例是什么 class ,尤其是它可以继承的超类。它也不关心方法的作用。
此外,以最抽象的方式引用对象是最佳实践,而在java中,接口是最抽象的类型(因为它对类层次结构没有限制) - 请参阅 Liskov substitution principle了解有关此概念的更多信息。
这种安排为您实施代码提供了极大的灵活性。
答案 1 :(得分:1)
接口肯定是挑战概念的理解。有时您需要提前知道某个方法将存在于给定类型上。在你的情况下,LibGDX有一个渲染方法。 LibGDX在某些时候需要调用一个render方法,但是LibGDX不知道该方法是如何实现的,它只知道它需要调用render。所以,他们说请实现这个界面并告诉我们如何渲染。然后,当我们调用render()时,我们将确保在正确的时间调用它并调用您的代码。
也许这可以用另一种方式说。有时,当您使用其他软件时,他们会为您做很多工作。在某些时候,你必须找到一种方法来挂钩他们提供的服务。通过实现该接口,您可以为render()提供一个实现,并且它们足够好,可以在适当的时候为您调用它,以便可以进行渲染。
接口允许多态性。从本质上讲,LibGDX可以在实现其接口的任何内容上调用render()。因为您已经实现了他们的接口,所以他们知道代码知道类中必须存在render()。这是多态的原因是因为许多不同的代码库将实现接口并提供自己的自定义render实现,然后LibGDX将很乐意调用他们的方法并运行该方法的实现。
希望有所帮助!
答案 2 :(得分:1)
将接口视为collection
abstract
方法。所以这个特殊的类可能在我的其他类中implemented
。这就是它inherits
的方法。
将其视为与此父类签订合同的子类,并承诺它将遵循与接口相同的行为。否则,它必须宣称自己是一个抽象类(这是另一个需要解决的问题)。
在Java中,我们不允许扩展多个类(而不是C#)以保持简单。但是,我们可以根据需要实现尽可能多的接口。
举个例子,苹果,橘子,蓝莓有什么共同之处?它们都是水果,因此“强迫”它们具有相同的特性我创建了一个Fruit接口,如下所示:
interface Fruit {
public void name();
public void colour();
}
然后在我的Apple课程中实现它们:
public class Apple implements Fruit{
public void name(){
System.out.println("Apple");
}
public void colour(){
System.out.println("Red");
}
}
因此Apple.java被迫使用name()和color()方法,因此我们永远不会遇到既没有名称和颜色的Apple对象!
希望能够清理它
另外,我建议检查 - Tutorials Point
因为他们发布了相当清晰的教程。为了将来参考,我强烈建议您在发布问题之前在StackOverflow上搜索答案,因为这会导致很多负面投票!
答案 3 :(得分:0)
它没有。界面只是一个契约。对于Java,这意味着如果存在实现该接口的具体Object,它将具有合同中定义的方法的实现。
一个简单的例子应该有助于证明:
<强> ExampleInterface.java 强>
public interface ExampleInterface {
int operation(int a, int b);
}
ExampleAddition.java - 使用add作为操作来实现接口。
public class ExampleAddition implements ExampleInterface {
@Override
public int operation(int a, int b) {
return a+b;
}
}
ExampleSubtraction.java - 使用减法作为操作实现接口。
public class ExampleSubtraction implements ExampleInterface {
@Override
public int operation(int a, int b) {
return a-b;
}
}
ExampleMain.java - 包含使用乘法作为操作的匿名内部类。
public class ExampleMain {
public static void main(String[] args) {
ExampleInterface first = new ExampleAddition();
ExampleInterface second = new ExampleSubtraction();
ExampleInterface third = new ExampleInterface() {
@Override
public int operation(int a, int b) {
return a*b;
}
};
System.out.println(first.operation(10,5));
System.out.println(second.operation(10,5));
System.out.println(third.operation(10,5));
}
}
那么这一切的重点是什么?好吧,重点是所有界面实现都是可以互换的,你可以使用你想要的任何一个。现在很明显,在这个例子中,它并不是特别有用。如果您拥有数据访问对象,并且希望使用不同的技术来访问数据层,那么它会更有用。您可能希望在生产中使用hibernate实现,并在本地开发中使用普通的旧JDBC实现,并使用Mockito版本进行测试。这一切都可以完成,因为它们共享一个共同的界面,它们实际上是相互替代的替代品。然而,在libGDX中,我怀疑只会有一个实现,但它仍然必须遵守相同的合同。这让他们编写了一个独立于具体实现的游戏循环。