我正在阅读一本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
。什么问题???
我知道答案必须明显,但我不知道。也许主要是因为我没有看到一些神奇的英语短语。请帮助我理解这一段的内容。
答案 0 :(得分:5)
String.substring()
的调用,则String
类及其substring()
方法必须在编译时可用。 Foo
和Bar
。这两个类都扩展了类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
。而你不能这样做。
那么我们可以用接口做什么呢?
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
}
有许多隐喻用于理解界面,最受欢迎的可能是契约的概念。对调用者说的是:“如果你需要完成X,我们就会完成它。不要担心怎么样,这不是你的问题。” (虽然“合同”一词通常用于更一般的意义,但要小心。)
或者换句话说:如果你想买一份报纸,你不在乎它是在超市,报刊经销商或街上的小摊位出售,你只想买报纸。因此,NewspaperVendor
在这种情况下是一个具有一种方法的接口:sellNewsPaper()
。如果有人后来决定在网上或门到门销售报纸,他们所需要做的只是实现界面,人们会从他们那里购买。
但我最喜欢的例子是商店橱窗里的小贴纸上写着“我们接受X,Y和Z信用卡”。这是界面最纯粹的现实世界的例子。商店可以出售任何东西(它们甚至可能不是商店,有些可能是餐馆),他们使用的读卡器也不同。但是你不关心所有这些,你看看标志,你知道你可以用你的卡支付。
答案 1 :(得分:1)
段落的关键是"类需要在编译时出现"第2行。课程更具体。接口是抽象的。
由于类是具体的,因此设计人员和程序员需要了解所有关于类结构和如何实现方法。接口更抽象的地方。 (它们仅包含抽象方法)。因此,程序员只需知道接口必须具有哪些方法以及这些方法的签名。他不需要详细了解这些是如何实施的。
因此,在创建子类时,使用接口更容易,更好。您只需要知道接口的方法签名。
使用具体类我们必须实现类层次结构中高级方法的功能,同时使用接口可以避免这个问题。 (有一个相关的多态性概念,你可能会在以后学习)