EffectiveJava——接口优于抽象类
Java程序设计语言提供两种机制,可以用来定义允许多个实现的类型:接口和抽象方法,这两者直接醉为明显的区别在于,抽象类允许某些方法的实现,但接口不允许,一个更为重要的区别在于,为了实现由抽象类定义的类型,类必须成为抽象类的一个子类。任何一个类,只要定义了所有必要的方法,并且遵守通用约定,它就被允许实现一个借口,而不管这个类是处于类层次的哪个位置。因为Java只允许单继承,所有抽象类作为类型定义受到类极大的限制。
现有的类很容易被更新,以实现新的接口。
如果你希望让两个类扩展同一个抽象类,就必须把抽象类放到类型层次结构的高处,以便这两个类的一个祖先成为它的子类。遗憾的是这样做会间接到伤害到类层次,迫使这个公共祖先到所有后代类都扩展这个新的抽象类,无论它对于这些后代类是否合适。
接口是定义混合类型的理想选择。
接口允许我们构造非层次结构的类型框架。
假如我们有两个接口,一个表示歌唱家,另一个表示作曲家,在现实生活中,有很多人即是歌唱家又是作曲家,如果是接口,我只需要同时实现这两个接口就可以,如果是抽象类,因为Java是单继承的,我就没有办法描述这一类的人。
虽然接口不允许包含方法的实现,但是,使用接口来定义类型并不妨碍你为程序猿提供实现上的帮助。通过对你导出的每个重要接口都提供一个抽象骨架的实现类,把接口和抽象类的优点都结合起来。接口的作用仍然是定义类型,但是骨架的实现类接管类所有与接口实现相关的工作。
骨架为接口提供实现上的帮助,但又不强加“抽象类被用作类型定义时”所特有的严格限制。对于接口大多数的实现来讲,扩展骨架实现类是个很显然的选择,但不是必须的。如果预制的类无法扩展骨架实现类,这个类始终可以收工实现这个接口。此外,骨架实现类仍然有助于接口的实现。实现类这个接口的类可以把对于这个接口方法的调用,转发到一个内部私有类的实例上,这个内部私有类扩展骨架实现类。这种方法被称作模拟多重继承。这项技术具有多重继承的绝大多数有点,同时又避免了相应的缺陷。
编写骨架实现类相对比较简单,只是有点单调乏味。首先,必须认真研究接口,并确定哪些方法时最为基本的,其他方法则可以根据它们来实现。这些方法将成为骨架实现类中的抽象方法。然后,必须为接口中的所有其他的方法提供具体实现。例如,下面是Map.Entry接口的骨架实现类:
/**
* 接口优于抽象类
* @author weishiyao
*
* @param <K>
* @param <V>
*/
// Skeletal Implementation
public abstract class AbstractMapEntry<K, V> implements Map.Entry<K, V>{ // Primitive operations
public abstract K getKey();
public abstract V getValue(); // Entries in modifiable maps must override this method
public V setValue(V value) {
throw new UnsupportedOperationException();
} // Implements the general contract of Map.Entry.equals
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Map.Entry)) {
return false;
}
Map.Entry<?, ?> arg = (Map.Entry) obj;
return equals(getKey(), arg.getKey()) && equals(getValue(), arg.getValue());
} private static boolean equals(Object obj1, Object obj2) {
return obj1 == null ? obj2 == null : obj1.equals(obj2);
} // Implements the general contract of Map.Entry.hashCode
@Override
public int hashCode() {
return hashCode(getKey()) ^ hashCode(getValue());
} private static int hashCode(Object obj) {
return obj == null ? 0 : obj.hashCode();
}
}
骨架实现类时为了继承的目的而设计的,这种使用方式在平时开发中经常可以见到,很多框架中都有使用方式,之前为也是见过好多次框架中这么使用,大致能明白这么写是干什么,这次经过这么详细讲解,算是彻底明白为什么要这么使用了,能想到这种写法的人真的也是大神了。
EffectiveJava——接口优于抽象类的更多相关文章
- Effective Java 第三版—— 20. 接口优于抽象类
Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...
- 从接口、抽象类到工厂模式再到JVM来总结一些问题
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习! 涉及到的知识点总结如下: 为什么使用接口? 接口和抽象类的区别 简单工厂模式总结 Java中new和newInstance的区别 J ...
- (转)深入理解Java的接口和抽象类
原文地址: http://www.cnblogs.com/dolphin0520/p/3811437.html 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP ...
- c++ 接口和抽象类
其实对抽象类与接口的区别一直是搞不太清楚,最近正在学习<设计模式>,期间用到了很多c++多态的知识.这是才恍然发现,是应该整理下这方面的知识了.但在翻阅书本.上网查阅资料之际,发现有篇文章 ...
- android中接口和抽象类的区别
最近发现很多基础有点生疏了,特地写一点博客来巩固一下.今天主要来谈谈接口和抽象类的区别,我们在项目的很多地方都会用到接口或者抽象类,但是它们之间的一些区别和相同点不知道大家有没有注意到,还有就是,什么 ...
- 深入理解Java的接口和抽象类(转)
深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...
- c#接口与抽象类的区别
abstract 修饰符用于表示所修饰的类是不完整的,并且它只能用作基类.抽象类与非抽象类在以下方面是不同的: 抽象类不能直接实例化,并且对抽象类使用 new 运算符是编译时错误.虽然一些变量和值在编 ...
- Java接口和抽象类的区别
今天看到项目中,写了一个抽象类,里面有很多方法继承了这类,当调用这个接口时,采用的是这个抽象类去调方法的,当时一想,这个不就是我们说的Java的多态的特征: 继承:存在继承关系的子类和父类 重写:子类 ...
- 深入理解Java的接口和抽象类
深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的 ...
随机推荐
- struts2:struts.xml配置文件详解
1. 几个重要的元素 1.1 package元素 package元素用来配置包.在Struts2框架中,包是一个独立的单位,通过name属性来唯一标识包.还可以通过extends属性让一个包继承另一个 ...
- Android Weak Handler:可以避免内存泄漏的Handler库
这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! android使用java作 ...
- CodeBlocks16.01+wxWidgets3.0.2
[环境] windows7 x64,CodeBlocks16.01,wxWidgets3.0.2 [步骤] 一.下载所需的文件: 1.codeblocks官网:http://www.codeblock ...
- GCC 4.8.2 编译安装
https://my.oschina.net/u/728245/blog/184550 摘要: GCC 4.8.2 在 CentOS 6.5 下编译安装小记,遇到一些问题并解决. 以前从没有升级过 ...
- 专访Linux嵌入式开发韦东山操作系统图书作者--转
CSDN学院讲师韦东山:悦己之作,方能悦人 发表于2015-04-28 08:09| 6669次阅读| 来源CSDN| 24 条评论| 作者夏梦竹 专访Linux嵌入式开发韦东山操作系统图书作者 摘要 ...
- UIView的响应链
父视图 和子视图的关联 只有当父视图 userInteractionEnabled=YES; 是其子视图才可响应 userInteractionEnabled=NO代表不接受响应 UIView的默认 ...
- p2p研究
p2p网络结构 中央集中式结构 无集中式非结构 混合式以超级节点结构 穿透原理 防火墙为克隆型(cone net),对称型(Symmetric NAT) 只有克隆型才能用打洞方式穿透 开源方案 htt ...
- Go加密解密之RSA[转]
安全总是很重要的,各个语言对于通用的加密算法都会有实现.前段时间,用Go实现了RSA和DES的加密解密,在这分享一下.(对于RSA和DES加密算法本身,请查阅相关资料) 在PHP中,很多功能经常是一个 ...
- c++ 全局变量初始化的一点总结
注意:本文所说的全局变量指的是 variables with static storage,措词来自 c++ 的语言标准文档. 什么时候初始化 根据 C++ 标准,全局变量的初始化要在 main 函数 ...
- 开发Chrome Extension截取你微博的帐号密码
Google允许开发者对Chrome浏览器做扩展,所以有了之前火爆的12306抢票软件,我 也用它抢过票,一直很好奇它怎么注入js到12306上面的.这周有空研究了下Chrome Extension, ...