8: Interfaces & Inner Classes(接口与内部类)

接口(interface)
当你implements一个interface的时候,你必须把这个interface的方法定义成public的。如果你不这么做,那它就会变成package权限的,这样经过继承,这些方法的访问权限就会受到限制,而这是Java的编译器所不允许的。
Java的“多重继承”
interface既给了你abstract类的好处,又给了你interface的好处,因此只要基类的设计里面可以不包括妇女干法和成员变量的定义,你就应该优先使用interface。
合并接口时的名字冲突
在合并的接口里面放上同名方法,通常也会破坏程序的可读性。
用继承扩展interface
通常情况下,extends只能用于类,但是由于一个interface可以由多个接口拼接而成,因此创建新的interface的时候可以用extends来表示其多个“基接口(base interfaces)”。interface的名字要由逗号分隔。
常量的分组
interface是一种非常方便的,创建一组常量值的工具。
这种方法通常被称为使用“神奇数字”,并且使得代码的维护变得非常困难。
初始化接口中的数据成员
这些数据都不算是接口的组成部分,相反它们保存在这个接口的静态存储区内。
接口的嵌套
实现private接口就成了一种“强制你区定义那个接口的方法,但是又不让你添加任何类型信息(也就是说不允许上传)”的手段了。
接口与接口也可以嵌套,不过接口的规则仍然有效——特别是接口的所有元素都必须是public的这条,因此嵌套在接口中的接口也都自动是public的,它们不能是private的。
特别要注意的是,实现接口的时候,不一定要实现嵌套在里面的接口。同样private接口只能在定义它的类里实现。

内部类
内部类是一种非常有价值的特性,它能让你在逻辑上将相互从属的类组织起来,并且在类的内部控制访问权限。但是切记,内部类和合成是截然不同的,这一点非常重要。
内部类与上传
普通类(非内部类)是不能被定义成private或protected的;它们只可能是public或package权限的。
在方法和作用域里的内部类
内部类可以被创建在方法内部,甚至是任何一个作用领域。这么做有两个理由:
1. 就像前面所说的,你在实现某个接口,这样你才能创建并且返回这个接口的reference。
2. 你正在处理一个复杂的问题,需要创建一个类,但是又不想让大家都知道还有这么一个类。
匿名内部类
如果你在定义匿名内部类的时候,还要用到外面的对象,那编译就会要求你把这个参数的reference声明成final的。如果你忘了,编译的时候就会报错。
实际上实例初始化过程就是匿名内部类的构造函数。当然,它的功能是有限的;你不能重载实例初始化,因此你只能有一个构造函数。
与宿主类的关系
嵌套类

如果你不需要这种“内部类对象和宿主类对象之间”的联系,那么你可以把内部类定义成static的。潜逃类的意思是:
1. 无须宿主类的对象就能创建嵌套类的对象。
2. 不能在嵌套类的对象里面访问非static的宿主类对象。
普通内部类的成员数据和方法只能到类的外围这一层,因此普通的内部类里不能有static数据,static数据成员或嵌套类。但是,这些东西嵌套类里都可以有。
普通(非static)的内部类需要使用特殊的this reference来与宿主类对象保持联系。而嵌套类不需要这个this reference,这就使得它与static方法有些相似了。
引用宿主类的对象
在多层嵌套的类里向外访问
继承内部类

等到要创建构造函数的时候,默认的构造函数玩不转了,你必须传给他宿主类对象的reference。此外,你还必须在构造函数里面使用这种语法:
enclosingClassReference.super();
这样才能提供那个必须的reference,而程序也才能编译通过。
内部类可以被覆写吗?
本地内部类(Local inner classes)
选择本地内部类而不是匿名内部类的唯一原因就是,你必须创建那种类的对象。
内部类的标识符(Inner class identifiers)

为什么要有内部类?
每个内部类都可以独立地继承某个“实现(implementation)”。因此,内部类不会受“宿主类是否已经继承了别的实现”的约束。
1. 内部类可以有多个实例,而每个又都可以有它自己的,与宿主类对象无关的状态信息。
2. 一个宿主类里可以放上好几个内部类,它们可以用各自不同的方式来实现同一个interface或继承同一个类。
3. 内部类对象创建的时机与宿主类对象的创建没什么关系。
4. 内部类不存在什么让人头晕的“是”关系;他是一个独立的实体。
Closure与回调(Closures & Callbacks)
创建内部类的时候,别去扩展或者修改宿主类的接口。
内部类与控制框架(Inner classes & control frameworks)
1. 在一个类里完整地实现整个控制框架,这样就把“实现”里的所有独一无二东西全部都给封装起来了。内部类则用来表示各种解决具体问题所需的action()。
2. 内部类可以让这个实现看上去不至于太古怪,因为它还可以直接访问宿主类的所有成员。要不是这样的话,代码就会变得非常杂乱,这样到最后你肯定会去找一个替代方案的。

总结

练习