JAVA接口与抽象类
增加了间接性,提升了灵活性。
应用时需要权衡两者的权重。通常应用于具体类变化可能性非常大的地方。
1 JAVA接口
接口就好比插座,构件就好比电器。只要新构件能与接口匹配,就能替换原有构件。
1.1 什么是接口
JAVA接口是一些方法特征的集合,源自系统中不断出现的方法,是一种逻辑上的抽象。实现JAVA接口的两个类往往完全不同,但却拥有一组相同方法,提供类似服务。
JAVA接口将方法特征与实现分割。JAVA接口就代表了一种角色,它包装了该角色的属性与操作,而实现类则扮演了这个角色的演员。
注:
JAVA中的方法特征是指,仅包括方法名字、参量的数目和种类。这也是方法重载时的依据。
方法置换:则还包括返回类型、抛出异常是否相同。
1.2 为什么使用接口
接口是可插入性的保证。
Gardener不管理Fruit到底是什么,只需调用相应接口即可完成与水果有关的工作。当前对象调用的具体类完全可以动态决定。
软件系统的规模越大,生命周期越长,接口的重要性就越大。接口保证了软件系统的灵活性、可扩展性和可插入性。
1.2.1 类型:
Java接口与抽象类用来声明新的类型。
Java设计师应当使用Java接口与抽象类来将软件单位与内部和外部耦合起来。
具体则表现为,用Java接口和抽象类来进行变量、参量和返回类型声明,以及数据类型转换。
类型常以等级结构和组织的。
1.3 Java接口常见用法
1.3.1 单接口方法:
使Java能够获得C语言中函数指针所具有的能力,存储和转移调用某个函数。
例程:感觉上理解有点问题。下面的类结构。
publicinterface FuncPointer {
void run ();
}
class FunctorA implements FuncPointer {
publicvoid run () {
System.out.println (this.toString ());
}
}
class FunctorB implements FuncPointer {
publicvoid run () {
System.out.println (this.toString());
}
}
//test.java
publicclass Test {
publicstaticvoid main ( String [] args) {
FuncPointer[] pointers = new FuncPointer[2];
pointers[0] = new FunctorA ();
pointers[1] = new FunctorB ();
for(int i = 0; i < pointers.length; i++)
pointers[i].run ();
}
}
1.3.2 标识接口
只有接口名,没有方法声明,仅表示实现它的类属于一个特定类型。
如Java中的Serializable与Remote
1.3.3 常量接口
用接口将常量封装。这是错误的使用方法。Java中就存在这种错误用法:ObjectStreamConstants,ZipConstants,DndConstants
interface Constants {
staticfinalintDATE_LEN = 10;
staticfinalintFILE_NAME_LEN = 100;
staticfinal String PSWD = "admain";
}
1.4 接口应用实例
《日落紫禁城》中描写奸臣嘴脸的诗:头尖身细白如银,上称没有头毫分,眼睛长在屁股上,只认衣衫不认人。
“生、旦、净、丑”,武松的行当便是武生,程雪娥的行当便是花旦。
2 抽象类
2.1 抽象类的定义
仅提供一个类型的部分实现(共享部分)。
不能创建实例,只能被继承。
编程应当针对抽象编程。
2.2 抽象类的用途
抽象类是用来继承的,具体类不应当用来继承。在继承关系形成的等级结构中,叶子节点应当是具体类,而内节点应当是抽象类(或Java接口)。
2.2.1 代码重构方式:
2.2.2 抽象类应用规范
共享代码,减少超类无用数据对内存的占用。
2.3 Peter Coad继承复用条件
继承代表“一般化到特殊化的关系”,基类表一般,衍生类表特殊。
PeterCoad继承条件:
l 子类是超类的一个特殊种类,而不是超类的一个角色。”Has-A”是聚合关系,”Is-A”才是继承关系。
l 永远不需要将子类换成另一个类的子类的情况。如果不确定,就不应当设计成当前超类的子类。
l 子类具有扩展超类的责任,而不是置换或注销超类的责任。如果子类要大量地置换超类行为,则不应当便其成为超类的子类。
l 只有在分类学角度有意义时,才可以使用继承。不要从工具类继承,而应当是聚合关系。
Coad条件是里氏代换原则的衍生物。