我已经阅读了帖子发布 SO 问题所需的研究工作量。我再次羞于将这个问题发布到一堆百万问题中。但我仍然不明白java中的接口。它们具有未实现的方法,然后为实现它们的每个类定义。我搜索了一下。接口用于支持 java 中的多重继承,也用于避免继承的(致命的)钻石死亡。我还遇到了Composition vs Inheritance,继承不是为了代码重用,而是为了多态。因此,当我有一个通用代码作为一个类来扩展它时,由于多重继承提供了使用接口的选项(如果我错了,请纠正我),它将不受支持。我还发现在大多数情况下定义通用实现是不可能的。那么有一个接口方法的通用定义(不是完美的通用实现)然后在必要的地方覆盖它有什么问题,为什么java不支持它。例如。当我有 100 个实现接口的类时,其中 70 个有一个共同的实现,而其他的有不同的实现。为什么我必须在超过 70 个类的接口中定义通用方法,为什么我不能在接口中定义它们,然后在其他 30 个类中覆盖它们,这使我免于在 70 个类中使用相同的代码。我对接口的理解错了吗?为什么我必须在超过 70 个类的接口中定义通用方法,为什么我不能在接口中定义它们,然后在其他 30 个类中覆盖它们,这使我免于在 70 个类中使用相同的代码。我对接口的理解错了吗?为什么我必须在超过 70 个类的接口中定义通用方法,为什么我不能在接口中定义它们,然后在其他 30 个类中覆盖它们,这使我免于在 70 个类中使用相同的代码。我对接口的理解错了吗?
7 回答
首先,Java 中的接口(从 Java 7 开始)没有代码。这只是一个定义,一个类必须履行的契约。
那么有一个接口方法的通用定义(不是完美的通用实现)然后在必要的地方覆盖它有什么问题,为什么java不支持它
是的,您可以在 Java 中做到这一点,而不仅仅是接口。假设我希望从这个Example
接口有一个默认实现method1
但未method2
实现:
interface Example {
public void method1();
public String method2(final int parameter);
}
abstract class AbstractExampleImpl implements Example {
@Override
public void method1() {
// Implement
}
}
现在想要使用这个method1
默认实现的类可以扩展AbstractExampleImpl
。这比在接口中实现代码更灵活,因为如果您这样做,那么所有类都绑定到您可能不想要的实现。这是接口的优点:能够引用某个行为(契约),而不必知道类是如何实际实现的,例如:
List<String> aList = MyListFactory.getNewList();
MyListFactory.getNewList()
可以返回任何实现的对象List
,我们的代码操作aList
根本不关心,因为它是基于接口的。
如果使用接口的类已经是子类怎么办。然后我们不能使用抽象类,因为不支持多重继承
我猜你的意思是这种情况:
class AnotherClass extends AnotherBaseClass
你也想扩展AbstractExampleImpl
。是的,在这种情况下,不可能进行AnotherClass
extend AbstractExampleImpl
,但是您可以编写一个包装的内部类来执行此操作,例如:
class AnotherClass extends AnotherBaseClass implements Example {
private class InnerExampleImpl extends AbstractExampleImpl {
// Here you have AbstractExampleImpl's implementation of method1
}
}
然后,您可以通过调用其方法在内部使所有Example
方法实际实现。InnerExampleImpl
有必要在AnotherClass中有接口吗?
我猜你的意思是AnotherClass implements Example
。好吧,这就是你想要的:用一些默认AnotherClass
实现Example
实现并扩展另一个类,否则我理解你错了。由于您不能扩展一个以上的类,因此您必须实现接口以便您可以做到
final Example anotherClass = new AnotherClass();
否则这是不可能的。
同样对于每个实现接口的类,我是否必须设计一个内部类?
不,它不必是内部类,这只是一个示例。如果您希望多个其他类具有此默认Example
实现,您只需编写一个单独的类并将其包装在您想要的所有类中。
class DefaultExampleImpl implements Example {
// Implements the methods
}
class YourClass extends YetAnotherClass implements Example {
private Example example = new DefaultClassImpl();
@Override
public void method1() {
this.example.method1();
}
@Override
public String method2(final int parameter) {
return this.example.method2(parameter);
}
}
您可以创建一个抽象类来实现该接口,并使您的这些类继承该抽象类,这应该是您想要的。
实现和接口的非抽象类需要实现接口中的所有方法。抽象类不必实现所有方法但不能初始化。如果您在示例中创建实现除一个之外的所有接口方法的抽象类。从这些抽象类扩展的类只需要实现一个尚未实现的方法。
Java 接口可以被称为契约,以更好地传达它们的意图。声明者承诺提供一些功能,并且使用代码保证对象提供该功能。
这是一个强大的概念,并且与在 Java 有点受限的情况下提供该功能的方式是分离的,而且您不是第一个注意到这一点的人。我个人发现很难提供只需要一个或两个子类就可以在给定情况下使用的“完美”实现。Swing 使用适配器来提供空实现,然后可以根据需要覆盖这些实现,这可能是您正在寻找的技术。
你应该先了解接口的基础。哪个是
- 它用于提供紧密耦合意味着紧密封装
- 它帮助我们从外部环境(即其他类)隐藏我们的代码
- 接口应该只有定义和数据是不变的
- 它为课堂开放提供设施以供扩展。因此它不能被java中的任何其他类替换,否则该类将变得关闭以进行扩展。这意味着类将无法扩展任何其他类。
接口的想法是创建一系列足够抽象的方法,以供实现它们的不同类使用。这个概念基于 DRY 原则(不要重复自己),接口允许您拥有像 run() 这样的方法,这些方法足够抽象,可用于游戏循环、玩家运行能力、
我认为您最关心的是面向对象设计的概念。在上面的示例中,您声明您有100
类,并且70
其中的类具有相同的方法实现(我会对此感到震惊)。所以给定一个这样的界面:
public interface Printable
{
void print();
}
和两个具有“相同”实现的类print
public class First implements Printable
{
public void print()
{
System.out.println("Hi");
}
}
public class Second implements Printable
{
public void print()
{
System.out.println("Hi");
}
}
你会想要这样做:
public abstract class DefaultPrinter implements Printable
{
public void print()
{
System.out.println("Hi");
}
}
现在First
和Second
public class First extends DefaultPrinter
{
}
public class Second extends DefaultPrinter
{
}
现在这两个都还在Printable
。现在,了解如何正确设计对象层次结构变得非常重要。如果某些东西不是DefaultPrinter
你不能也不应该让新类扩展DefaultPrinter