了解Java接口原理

Sal*_*van 2 java extends interface class-hierarchy subclassing

我正在阅读一本Java书,并且这次再次思考这一段实际意味着什么:

接口旨在支持运行时的动态方法解析.通常,为了从一个类调用方法到另一个类,两个类都需要在编译时出现,因此Java编译器可以检查以确保方法签名是兼容的.这个要求本身就是一个静态和不可扩展的分类环境.在这样的系统中,不可避免地会在类层次结构中将功能提升得越来越高,以便机制可用于越来越多的子类.接口旨在避免此问题.它们将方法或方法集的定义与继承层次结构断开连接.由于接口与类的层次结构不同,因此在类层次结构方面不相关的类可能实现相同的接口.这是实现接口真正功能的地方.

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

第二个问题:作者再次提出什么意思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.什么问题???

我知道答案必须明显,但我不知道.也许主要是因为我没有看到一些神奇的英语短语.请帮助我理解这一段的内容.

biz*_*lop 5

  1. 在任何两个班级之间.String.substring()例如,如果您的代码包含调用,则String该类及其substring()方法必须在编译时可用.
  2. 如上所述,"make for"意思与"创造"相同.环境是不可扩展的,因为您可能想要使用的所有内容都必须在编译时可用.(但这并非100%正确.即使没有接口,抽象类和方法也提供了扩展点,但它们并不像我们将要看到的那样灵活.)
  3. 想象一下,你有两个类:FooBar.这两个类都扩展了类Thingy.但是,您想要添加一个新功能,假设您希望在网页上以HTML格式显示.所以你要为这两个方法添加一个方法.

基本问题

  abstract class Thingy { ... }

  class Foo extends Thingy {
     ...
     public String toHTMLString() {
        ...
     }
  }

  class Bar extends Thingy {
     ...
     public String toHTMLString() {
        ...
     }
  }
Run Code Online (Sandbox Code Playgroud)

这很棒,但你怎么称呼这种方法?

 public String createWebPage( Thingy th ) {
    ...
    if (th instanceof Foo)
       return ((Foo)th).toHTMLString();
    if (th instanceof Bar)
       return ((Bar)th).toHTMLString();
    ...
 }
Run Code Online (Sandbox Code Playgroud)

显然,这种方式根本不灵活.所以,你可以做什么?好吧,你可以推进toHTMLString()他们共同的祖先,Thingy.(这就是本书所讨论的内容.)

一个天真的尝试来解决它

  abstract class Thingy {
     ...
     public abstract String toHTMLString();
  }

  class Foo extends Thingy {
     ...
     public String toHTMLString() {
        ...
     }
  }

  class Bar extends Thingy {
     ...
     public String toHTMLString() {
        ...
     }
  }
Run Code Online (Sandbox Code Playgroud)

然后你可以这样称呼它:

 public String createWebPage( Thingy th ) {
    ...
    return th.toHTMLString();
 }
Run Code Online (Sandbox Code Playgroud)

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

带接口的解决方案

那么我们可以用接口做什么呢?

  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() {
        ...
     }
  }     
Run Code Online (Sandbox Code Playgroud)

调用代码将是简单的

 public String createWebPage( HTMLPrintable th ) {
    ...
    return th.toHTMLString(); // "implements HTMLPrintable" guarantees that this method exists
 }
Run Code Online (Sandbox Code Playgroud)

接口是什么?

有许多隐喻用于理解界面,最受欢迎的可能是契约的概念.对调用者说的是:"如果你需要完成X,我们就会完成它.不要担心怎么样,这不是你的问题." (虽然"合同"一词通常用于更一般的意义,但要小心.)

或者以另一种方式:如果你想买报纸,你不在乎它是在超市,报刊经销商或街上的小摊位出售,你只想买报纸.所以NewspaperVendor在这种情况下是一个带有一种方法的接口:sellNewsPaper().如果有人后来决定在网上或门到门销售报纸,他们所需要做的只是实现界面,人们会从他们那里购买.

但我最喜欢的例子是商店橱窗里的小贴纸上写着"我们接受X,Y和Z信用卡".这是界面最纯粹的现实世界的例子.商店可以出售任何东西(它们甚至可能不是商店,有些可能是餐馆),他们使用的读卡器也不同.但是你不关心所有这些,你看看标志,你知道你可以用你的卡支付.