- 写在前面的话
- 引言
- 第 1 章 对象入门
- 第 2 章 一切都是对象
- 第 3 章 控制程序流程
- 第 4 章 初始化和清除
- 第 5 章 隐藏实施过程
- 第 6 章 类再生
- 第 7 章 多形性
- 第 8 章 对象的容纳
- 第 9 章 违例差错控制
- 第 10 章 Java IO 系统
- 第 11 章 运行期类型鉴定
- 第 12 章 传递和返回对象
- 第 十三 章 创建窗口和程序片
- 第 14 章 多线程
- 第 15 章 网络编程
- 第 16 章 设计范式
- 第 17 章 项目
- 附录 A 使用非 JAVA 代码
- 附录 B 对比 C++和 Java
- 附录 C Java 编程规则
- 附录 D 性能
- 附录 E 关于垃圾收集的一些话
- 附录 F 推荐读物
7.6.1 内部类和上溯造型
迄今为止,内部类看起来仍然没什么特别的地方。毕竟,用它实现隐藏显得有些大题小做。Java 已经有一个非常优秀的隐藏机制——只允许类成为“友好的”(只在一个包内可见),而不是把它创建成一个内部类。
然而,当我们准备上溯造型到一个基础类(特别是到一个接口)的时候,内部类就开始发挥其关键作用(从用于实现的对象生成一个接口句柄具有与上溯造型至一个基础类相同的效果)。这是由于内部类随后可完全进入不可见或不可用状态——对任何人都将如此。所以我们可以非常方便地隐藏实施细节。我们得到的全部回报就是一个基础类或者接口的句柄,而且甚至有可能不知道准确的类型。就象下面这样:
//: Parcel3.java // Returning a handle to an inner class package c07.parcel3; abstract class Contents { abstract public int value(); } interface Destination { String readLabel(); } public class Parcel3 { private class PContents extends Contents { private int i = 11; public int value() { return i; } } protected class PDestination implements Destination { private String label; private PDestination(String whereTo) { label = whereTo; } public String readLabel() { return label; } } public Destination dest(String s) { return new PDestination(s); } public Contents cont() { return new PContents(); } } class Test { public static void main(String[] args) { Parcel3 p = new Parcel3(); Contents c = p.cont(); Destination d = p.dest("Tanzania"); // Illegal -- can't access private class: //! Parcel3.PContents c = p.new PContents(); } } ///:~
现在,Contents 和 Destination 代表可由客户程序员使用的接口(记住接口会将自己的所有成员都变成 public 属性)。为方便起见,它们置于单独一个文件里,但原始的 Contents 和 Destination 在它们自己的文件中是相互 public 的。
在 Parcel3 中,一些新东西已经加入:内部类 PContents 被设为 private,所以除了 Parcel3 之外,其他任何东西都不能访问它。PDestination 被设为 protected,所以除了 Parcel3,Parcel3 包内的类(因为 protected 也为包赋予了访问权;也就是说,protected 也是“友好的”),以及 Parcel3 的继承者之外,其他任何东西都不能访问 PDestination。这意味着客户程序员对这些成员的认识与访问将会受到限制。事实上,我们甚至不能下溯造型到一个 private 内部类(或者一个 protected 内部类,除非自己本身便是一个继承者),因为我们不能访问名字,就象在 classTest 里看到的那样。所以,利用 private 内部类,类设计人员可完全禁止其他人依赖类型编码,并可将具体的实施细节完全隐藏起来。除此以外,从客户程序员的角度来看,一个接口的范围没有意义的,因为他们不能访问不属于公共接口类的任何额外方法。这样一来,Java 编译器也有机会生成效率更高的代码。
普通(非内部)类不可设为 private 或 protected——只允许 public 或者“友好的”。
注意 Contents 不必成为一个抽象类。在这儿也可以使用一个普通类,但这种设计最典型的起点依然是一个“接口”。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论