是否有必要或约定设计一些特定的 class 来调用我们界面中的方法

Is there a necessity or a convention of designing some specific class that invokes the methods in our interface

我们在创建接口的时候只创建接口就够了吗? 还是我们必须设计另一个调用接口方法的特定 class?

代上一版本题更正

正如下面的问题所指出的,当我们设计一个接口时,可以使用默认方法来设计它。所以在那种情况下,我们不需要设计一些特定的 class 来调用该接口的未实现方法。因为用户可以使用接口来调用那些默认方法。

所以现在我的问题是,当我们的接口没有实现任何默认方法而只有未实现的方法时,我们是否需要设计一些特定的 class/classes 来调用那些未实现的方法,以便工作那个实现我们接口的interface/classes?

正如@ruakh 在评论中指出的那样:

No code ever has an effect if you don't use it. Why would interfaces be different?

如果您创建一个接口,您就告诉编译器该类型的所有 classes 必须有一些方法。

如果您实现接口,则实现会为这些方法提供代码。

您不能实例化接口,但可以实例化(非抽象)class实现接口的实体。

据此,没有实现的接口将毫无用处,但也有一些例外:

  • 静态方法 无需接口的对象(或实现)即可调用。但是仅使用静态方法创建接口并没有真正的目的。您还可以使用私有构造函数创建 class。

  • Lamdas 也只是接口,但实现被翻译成匿名 class,这意味着有一个实现。(见评论来自@kaya3)

    As a side note, technically when you write a lambda or a method reference you are not writing a class, so if you write a functional interface (i.e. an interface with only one abstract method), then you can use that interface without writing a class that implements it. But I suspect that is not the kind of answer you were looking for.

  • 如果您创建一个 API,您可能想要创建一个由其他人实现的接口。实现不在您的代码中,但接口在。

接口的主要目的是声明一个契约,说明可以用将永远实现这个接口的对象来做什么。

因此,当您创建一个接口时,您实质上是通过声明契约来定义一种能力,一种系统的特性。

现在在你这样做之后,你可以决定是否立即实现这个接口,在很多情况下,如果这种情况是你现在正在处理的系统的内部部分,或者在其他情况下,你会立即实现它在此特定功能中,系统是"closed"。在这种情况下,可以有一个实现,也可以有多个实现。

这方面的一个例子是,如果您设计某些功能,则需要多态行为。比方说,你设计了一个类似 "word" 的系统(文本处理器),你需要以不同的格式保存文档,所以你可能会得到类似的结果:

public interface DocumentSaveHandler {
   void save(Document doc);
}

public class PdfSaveHandler {
 void save(Document doc) { 
   // save the document in the pdf format
 }
}

public class TextSaveHandler {
 void save(Document doc) { 
   // save the document in the textual format
 }
}

或者,您可以声明稍后将实施的合同(由您、您的同事、您未来的客户,如果您从事某种 API,或者甚至在构建时自动生成或在 运行 时间内(自动生成的代理))

例如,以 Java 8 中添加的所有功能接口为例。这些通常与流一起使用(也是 Java 8 的一个特性),但流的设计者选择了提供界面,他们不知道他们将被谁使用以及如何使用。所以在这种情况下,它是 API 的一部分(此时打开系统)。

另一个例子,假设您设计了一个库并在文档中指定:"In Order to use my library the user must implement the interface XYZ"(因此提供了 inteface XYZ 提供的功能的实际实现。在这种情况下,你定义了一个你自己无法实现的契约,因为你不知道足够的细节,因此你只提供了没有实现的接口,但未来的用户肯定可以实现你的接口。

更新

由于 OP 对我的回答的评论:

您应该始终尝试针对接口而不是实现进行编程。在您在评论中提出的示例中,应该有一个 class 采用 DocumentSaveHandler 而不是具体实现。

在 运行 时间里,具体的实现将被传递到那里,但编译不需要具体的实现。

这是一个例子:


public class Word {

   private Map<String, DocumentSaveHandler> handlers; // note its the interface, not an implementation - map of supported types to the actual handler


   public onSaveButtonPressed(String selectedDocType) {
      Document doc = getDocumentToSave();
      DocumentSaveHandler handler  =  handlers.get(selectedDocType);
      handler.save(doc);
   } 
}

注意,我从未使用过具体的实现。我假设它将由初始化整个 Word 文本处理器的代码提供。 所以即使 DocumentSaveHandler

没有真正的实现,这段代码也会编译

这个例子有点复杂,但即使在没有地图的更简单的情况下,您仍然使用界面而不是真正的实现