java - 了解 Java 接口(interface)原理

标签 java interface extends subclassing class-hierarchy

我正在阅读一本 Java 书籍,这次我再次陷入思考这整个段落的实际含义:

Interfaces are designed to support dynamic method resolution at run time. Normally, in order for a method to be called from one class to another, both classes need to be present at compile time so the Java compiler can check to ensure that the method signatures are compatible. This requirement by itself makes for a static and nonextensible classing environment. Inevitably in a system like this, functionality gets pushed up higher and higher in the class hierarchy so that the mechanisms will be available to more and more subclasses. Interfaces are designed to avoid this problem. They disconnect the definition of a method or set of methods from the inheritance hierarchy. Since interfaces are in a different hierarchy from classes, it is possible for classes that are unrelated in terms of the class hierarchy to implement the same interface. This is where the real power of interfaces is realized.



第一个问题:作者说from one class to another是什么意思?他的意思是这些类在层次结构方面是相关的吗?我的意思是,将子类对象引用分配给它的父类(super class)类型变量,然后调用一个方法?

第二个问题:作者再次说This requirement by itself makes for a static and nonextensible classing environment是什么意思? ?我不明白 makes for含义(英语不是我的主要语言)以及为什么将环境称为静态且不可扩展。

第三个问题:他说functionality gets pushed up higher and higher是什么意思?为什么它被推得越来越高?什么功能?另外,mechanisms will be available to more and more subclasses.什么机制?方法?

第四个问题:Interfaces are designed to avoid this problem .什么问题???

我知道答案一定很明显,但我不知道。也许主要是因为我不明白一些神奇的英语短语。请帮助我理解整段的内容。

最佳答案

  • 任意两堂课之间。如果您的代码包含对 String.substring() 的调用例如,String类及其substring()方法必须在编译时可用。
  • 如前所述,“制造”与“创造”的含义相同。该环境是不可扩展的,因为您可能想要使用的所有内容都必须在编译时可用。 (虽然这不是 100% 正确的。即使没有接口(interface)存在,抽象类和方法也提供扩展点,但正如我们将要看到的那样,它们不是很灵活。)
  • 假设你有两个类:FooBar .这两个类都扩展了类 Thingy .但是随后您想添加一个新功能,假设您想在网页上以 HTML 格式显示两者。因此,您向两者都添加了一个方法。

  • 基本问题
      abstract class Thingy { ... }
    
      class Foo extends Thingy {
         ...
         public String toHTMLString() {
            ...
         }
      }
    
      class Bar extends Thingy {
         ...
         public String toHTMLString() {
            ...
         }
      }
    

    这很好,但你怎么称呼这个方法?
     public String createWebPage( Thingy th ) {
        ...
        if (th instanceof Foo)
           return ((Foo)th).toHTMLString();
        if (th instanceof Bar)
           return ((Bar)th).toHTMLString();
        ...
     }
    

    显然这种方式根本不灵活。所以,你可以做什么?嗯,你可以推toHTMLString()直到他们共同的祖先,Thingy . (这就是这本书所说的。)

    天真的尝试解决它
      abstract class Thingy {
         ...
         public abstract String toHTMLString();
      }
    
      class Foo extends Thingy {
         ...
         public String toHTMLString() {
            ...
         }
      }
    
      class Bar extends Thingy {
         ...
         public String toHTMLString() {
            ...
         }
      }
    

    然后你可以这样称呼它:
     public String createWebPage( Thingy th ) {
        ...
        return th.toHTMLString();
     }
    

    成功!除了现在你已经强制每个类扩展 Thingy实现 toHTMLString()方法,即使它对其中一些人没有意义。更糟糕的是,如果这两个对象没有明确扩展任何东西,它们完全不相关怎么办?您必须将方法一直推到它们的共同祖先中,即 java.lang.Object .而你不能那样做。

    带接口(interface)的解决方案

    那么我们可以用接口(interface)做什么呢?
      abstract class Thingy { ... }
    
      interface HTMLPrintable {
         public String toHTMLString();
      }         
    
      class Foo extends Thingy implements HTMLPrintable {
         ...
         public String toHTMLString() {
            ...
         }
      }
    
      class Bar extends Thingy implements HTMLPrintable {
         ...
         public String toHTMLString() {
            ...
         }
      }
    
      //We've added another class that isn't related to all of the above but is still HTMLPrintable,
      //with interfaces we can do this.
      class NotEvenAThingy implements HTMLPrintable { 
         public String toHTMLString() {
            ...
         }
      }     
    

    调用代码将很简单
     public String createWebPage( HTMLPrintable th ) {
        ...
        return th.toHTMLString(); // "implements HTMLPrintable" guarantees that this method exists
     }
    

    那什么是接口(interface)呢?

    用于理解接口(interface)的比喻有很多,最流行的可能是契约的概念。它对调用者说的是:“如果你需要完成 X,我们会完成它。不要担心如何,这不是你的问题。” (虽然“契约(Contract)”这个词经常用于更一般的意义,所以要小心。)

    或者换一种说法:如果你想买一份报纸,你不在乎它是在超市、报刊亭还是街上的小摊上卖的,你只想买一份报纸。所以NewspaperVendor在这种情况下是一个具有一种方法的接口(interface):sellNewsPaper() .如果后来有人决定在网上或上门销售报纸,他们所要做的就是实现接口(interface),人们就会从他们那里购买。

    但我最喜欢的例子是商店橱窗里的小贴纸,上面写着“我们接受 X、Y 和 Z 信用卡”。这是接口(interface)的最纯粹的真实示例。商店可以卖任何东西(他们甚至可能不是商店,有些可能是餐馆),他们使用的读卡器也不同。但你并不关心所有这些,你看看标志,你就知道你可以在那里用你的卡支付。

    关于java - 了解 Java 接口(interface)原理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26056396/

    相关文章:

    java - 我现在正在使用 SAX 进行解析

    c# - 为什么接口(interface)实现不能返回更具体的类型?

    javascript - Typescript - 在不实现接口(interface)父级的情况下实现接口(interface)

    java - 解决JAVA父接口(interface)中缺少构造函数

    java - 使用 org.springframework.data.jpa.repository.Query 使用列表参数有条件删除

    java - Spring Boot 事件监听器不接收事件

    java - 这段java代码是如何执行代码的?

    使用模板实现接口(interface)的c++编译错误

    java - 使用组合和继承时避免 Java 中的菱形

    java - IDEA 和 Eclipse : How to automatic generate method when extends a class