近来对抽象类跟接口搞不太清楚,在网上查了些资料,汇总如下,有什么不对的地方还请大家指正
比较
抽象层次从高到底:接口->抽象类->具体实现类
行为的抽象,是规则,接口, (是特殊的个性)
事物的抽象,是共性,是抽象类(是一般的共性)
抽象类理解:抽象类往往用来表征我们在对问题领域进行分析、 设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象,我们不能把它们实例化(拿不出一个具体的东西)所以称之为抽象。比如:我们要描述“水果”,它就是一个抽象,它有质量、体积等一些共性(水果有质量),但又缺乏特性(苹果、橘子都是水果,它们有自己的特性),我们拿不出唯一一种能代表水果的东西(因为苹果、橘子都不能代表水果),可用抽象类来描述它,所以抽象类是不能够实例化的。当我们用某个类来具体描述“苹果”时,这个类就可以继承描述“水果”的抽象类,我们都知道“苹果”是一种“水果”。
1.接口中定义了一些方法,但是没有实现。
2.在接口的具体实现类中,如果有共同的实现<部分>,可用一个抽象类来实现这些共同的部分;个性化的实现交给具体实现类<子类>完成。
3.抽象类提供了公共方法的实现,抽象类提高代码复用能力
1、abstract class 和 interface有什么异同?
答:
1)抽象类可以有实现(包括构造函数),而接口不可以有任何实现,重要的是抽象类可以包括抽象方法,这是普通类所不能的。抽象方法只能声明于抽象类中,且不包含任何实现,派生类必须覆盖它们。接口中所有方法都必须是未实现的。
2)抽象类中还以有成员变量(包含静态成员变量)、属性、常量和静态方法,并且他们可以是非公共的;而接口中不能有成员变量、常量、静态方法,只能有公共的属性。
3)抽象类可以从另一个类或者一个/ 多个接口派生;而接口不能从另一个类派生却可以实现另一个或多个接口。
4)一个.net 类只能从一个基类中派生即使这个基类是抽象类;然而一个.net 类可以实现多个接口。(但是如果从一个抽象类派生或者从一个/ 多个接口实现,则必须实现抽象类中抽象方法或接口中所有的方法)
相同点:
1)不能实例化;
2)包含未实现的方法声明;
3)派生类必须实现未实现的方法,抽象类是抽象方法,接口则是所有成员(不仅是方法包括其他成员);
抽象类和接口的使用:
1)如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单的方法来控制组件版本。
2)如果创建的功能将在大范围的全异对象间使用,则使用接口。如果要设计小而简练的功能块,则使用接口。
3)如果要设计大的功能单元,则使用抽象类.如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。
4)抽象类主要用于关系密切的对象;而接口适合为不相关的类提供通用功能。
使用场景
1 优先定义接口
2 如果有多个接口实现有公用的部分,则使用抽象类(代码复用),然后继承它。
包含抽象方法的类即为抽象类,当一个抽象类中所有的方法都是抽象时,我们就可以定义成接口。
在设计类时,如果有些方法我们能确定,而有些方法不能确定,这时候我们就可以把该类声明成抽象类。抽象类的应用场景非常多,例如模板方法模式就是抽象类的一个应用, JDK中的inputStream和outputStream也是抽象类的一个应用,这两个类定义了如何读写数据的方法,而没有定义从哪里去读,具体从哪里读由具体的实现子类确定。
我们在定义相互调用规则时,可以使用接口。面向接口进行编程的明显好处,就是能极大降低软件系统的相互耦合性,接口的定义者按照接口进行调用,而实现者去实现接口。
在JDK中存在许多针对于接口的编程,例如用于比较对象的Comparable接口就是一个典型案例,我们在自定义对象时,如果实现了该接口,那么我们把对象保存到treeset集合中时,treeset将针对接口调用对象的compareTo方法。
看下面学生的例子:
abstract class AbstractStudent {
abstract void study();
void sleep() {
System.out.println("sleep");
}
void smoke() {
System.out.println("抽烟");
}
}
//所有的Student被创建都会抽烟,是不是很搞笑?
class Student extends AbstractStudent{
tudent Demo stu = new Student();
...
}
上面这个学生抽象类中有三个方法,学习,睡觉,抽烟。我们知道任何一个学生都要学习,都要睡觉,但是不是每个学生都要抽烟呢?这显然是不合理的。难道说创建一个学生对象,就一定要强加给他抽烟的方法?就像一个学生来了,就一定要他会抽烟?女生也不放过?哈哈!这显然是很荒唐的事情。
于是我们做如下调整:abstract class AbstractStudent {
abstract void study();
void sleep() {
System.out.println("sleep");
}
}
interface Smoking{
void smoke();
}
//普通的学生,继承AbstractStudent,有学习、睡觉的方法,不抽烟
class Student extends AbstractStudent{
}
//抽烟的学生,除了继承AbstractStudent中的方法,还会抽烟
class SmokeStudent extends AbstractStudent implements Smokeing{
}
这样,就把抽烟的同学和不抽烟的同学分离开了。
总结:抽象类中通常放的是类种事物(对象)共有的属性和方法,于是它的子类继承它的时候就自然有了其所有属性和方法,当有些方法是某种子类特有的时,就应该将这个方法分离出来,以附加的形式(implements)添加进去。
相关引用:
http://blog.sina.com.cn/s/blog_62dae6060100lsg1.html (抽象层次)
http://www.cnblogs.com/m3Lee/archive/2013/06/05/3119148.html (门的例子)
http://blog.csdn.net/boyxiaolong/article/details/7841773
http://www.tarena.com.cn/student/452.jhtml (学生的例子)
http://wenku.baidu.com/view/0612ed1fff00bed5b9f31dcb.html (abstract class 和 interface有什么异同?)
http://my.oschina.net/lchl/blog/11635 (面向接口编程)