1. 首页
  2. IT资讯

「Java学习交流」接口与抽象类的区别

“u003Cdivu003Eu003Cpu003E在Java语言中, abstract class 和interface 是抽象类定义的两种机制。由于这两种机制的存在,让Java有了强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性,甚至可以相互替换,因此有的人在进行抽象类定义时对于abstract class和interface的选择显得比较随意。其实,对于abstract class 和interface这两者之间还是有很大区别的,对于它们的选择也反映出对它们的理解。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E理解抽象类u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E 在面向对象中,所有的类都是通过对象来进行描述的,但是,反过来,并不是所有的类都是描述对象的,如果一个类没有用足够的信息来描述一个详细的对象,那么这个类就是抽象类,这个抽象类往往是对对象进行分析设计而得出的一个抽象的概念。是对看上去不同,但是本质上没有任何差别的一类对象的抽象概念。就像我们喜欢的一些东西,像猫、狗、鸟,它们都属于动物,但是它们各自又有自己的特征。所以在面向对象中,我们可以将它们固定的一组的行为抽象出来,但是这些行为又有自己的实现方式,它们的特征是不同的。这些抽象出来的综合在一起就构成了抽象类,而对这组中任意的抽象的对象进行具体的描述,这样就构成了派生类。还是用猫、狗、鸟来说,它们都会叫,把这个叫抽象出来,建立抽象类,下面具体的类,继承这个类,对类猫、狗、鸟来进行具体描述,这个叫是怎么叫的,是如何表达出来的。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003Eabstract class 和interface分析u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E在语法上,abstract class 和interface的写法是不同的。下面来具体说明:u003Cu002Fpu003Eu003Cpu003Eabstract class :u003Cu002Fpu003Eu003Cpu003E[java] view plain copyu003Cu002Fpu003Eu003Cpu003E<span style=”font-size:18px;”>abstract calss Door{ u003Cu002Fpu003Eu003Cpu003E public abstract void Open(); u003Cu002Fpu003Eu003Cpu003E public abstract void Close(); u003Cu002Fpu003Eu003Cpu003E} u003Cu002Fpu003Eu003Cpu003Eclass Door1 extends Door u003Cu002Fpu003Eu003Cpu003E{ u003Cu002Fpu003Eu003Cpu003E public void Open(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door1 Open”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E public void Close(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door1 Close”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E public void Broken(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door1 Broken”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E}<u002Fspan> u003Cu002Fpu003Eu003Cpu003Einterface:u003Cu002Fpu003Eu003Cpu003E[java] view plain copyu003Cu002Fpu003Eu003Cpu003E<span style=”font-size:18px;”>public interface Door{ u003Cu002Fpu003Eu003Cpu003E public static final int id=1; u003Cu002Fpu003Eu003Cpu003E public void Open(); u003Cu002Fpu003Eu003Cpu003E public void Close(); u003Cu002Fpu003Eu003Cpu003E} u003Cu002Fpu003Eu003Cpu003Epublic cass Door1 implements Door{ u003Cu002Fpu003Eu003Cpu003E public void Open(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door1 Open”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E public void Close(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door2 Close”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E}<u002Fspan> u003Cu002Fpu003Eu003Cpu003E 在abstract class方式中,可以有自己的数据成员,也可以有非 abstract的成员方法,而在interface方式的实现中,只能够有静态的不能被修改的数据成员,也就是必须是static final 的,但是在interface中一般不定义数据成员,所有的成员方法都是abstract的。从某种意义上来说,interface其实是一种特殊的 abstract class。u003Cu002Fpu003Eu003Cpu003E 如果此时对于Door这个东西,不仅具有这些功能,还需要增加一个报警的功能,那么,此时我们又应该如何设计呢?u003Cu002Fpu003Eu003Cpu003E abstract classu003Cu002Fpu003Eu003Cpu003E[java] view plain copyu003Cu002Fpu003Eu003Cpu003E<span style=”font-size:18px;”>abstract calss Door{ u003Cu002Fpu003Eu003Cpu003E public abstract void Open(); u003Cu002Fpu003Eu003Cpu003E public abstract void Close(); u003Cu002Fpu003Eu003Cpu003E public abstract void Alarm(); u003Cu002Fpu003Eu003Cpu003E} u003Cu002Fpu003Eu003Cpu003Eclass Door1 extends Door u003Cu002Fpu003Eu003Cpu003E{ u003Cu002Fpu003Eu003Cpu003E public void Open(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door1 Open”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E public void Close(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door1 Close”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E public void Alarm(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door1 Alarm”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E}<u002Fspan> u003Cu002Fpu003Eu003Cpu003Einterface:u003Cu002Fpu003Eu003Cpu003E[java] view plain copyu003Cu002Fpu003Eu003Cpu003E<span style=”font-size:18px;”>public interface Door{ u003Cu002Fpu003Eu003Cpu003E public static final int id=1; u003Cu002Fpu003Eu003Cpu003E public void Open(); u003Cu002Fpu003Eu003Cpu003E public void Close(); u003Cu002Fpu003Eu003Cpu003E public void Alarm(); u003Cu002Fpu003Eu003Cpu003E} u003Cu002Fpu003Eu003Cpu003Epublic cass Door1 implements Door{ u003Cu002Fpu003Eu003Cpu003E public void Open(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door1 Open”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E public void Close(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“Door2 Close”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E}<u002Fspan> u003Cu002Fpu003Eu003Cpu003E 这种方法虽然也能实现,但是在Door的定义中把Door概念本身固有的行为方法和另外一个概念”报警器”的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的对象会因为”报警器”这个概念的改变而改变。另外,举个例子,如果有扇门,他没有报警的功能,只有开和关,此时的抽象类就不再起作用,对它没作用,要么重新写抽象类,要么都写在一个类中,抽象思想就不再有作用。但是这丝毫不会影响接口,它同样能实现想要的效果。u003Cu002Fpu003Eu003Cpu003E 再看,既然说Open、Close和Alarm属于两个不同的概念,我们就可以把它们分别定义在代表这两个概念的抽象类中。定义方式有:u003Cu002Fpu003Eu003Cpu003E 第一:这两个概念都使用 abstract class 方式定义;u003Cu002Fpu003Eu003Cpu003E 第二:两个概念都使用interface方式定义;u003Cu002Fpu003Eu003Cpu003E 第三:一个概念使用 abstract class 方式定义,另一个概念使用interface方式定义。u003Cu002Fpu003Eu003Cpu003E此时,问题又来了,对于Java来说,Java语言不支持多重继承,所以都使用abstract class方式来定义是不可行的。但是后面两种方式都是可行的。u003Cu002Fpu003Eu003Cpu003E 如果都使用interface方式来定义,那么就反映出对于那种特殊的AlarmDoor本质上到底是Door还是报警器?我们通过对其分析发现AlarmDoor在本质上和Door是相同的,都是Door,只是这个AlarmDoor还有报警的功能,但是我们现在又这么设计,合理吗?那么我们该如何来设计实现,明确的反映出我们的意思呢?u003Cu002Fpu003Eu003Cpu003E abstract class在Java语言中表示一种继承关系,它反映出来什么是什么的一个关系。所以对于Door这个概念,我们应该使用abstarct class方式来定义。对于AlarmDoor的报警功能,只能说除了共性外,它还有一个特性,那就是报警,这样,就可以通过interface方式定义。即:u003Cu002Fpu003Eu003Cpu003E[java] view plain copyu003Cu002Fpu003Eu003Cpu003E<span style=”font-size:18px;”>abstract class Door{ u003Cu002Fpu003Eu003Cpu003E abstract void open(); u003Cu002Fpu003Eu003Cpu003E abstract void close(); u003Cu002Fpu003Eu003Cpu003E} u003Cu002Fpu003Eu003Cpu003Einterface Alarm{ u003Cu002Fpu003Eu003Cpu003E void alarm(); u003Cu002Fpu003Eu003Cpu003E} u003Cu002Fpu003Eu003Cpu003Eclass AlarmDoor extends Door implements Alarm{ u003Cu002Fpu003Eu003Cpu003E void open(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“AlarmDoor Open”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E void close(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“AlarmDoor Close”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E void alarm(){ u003Cu002Fpu003Eu003Cpu003E System.out.println(“AlarmDoor Alarm”); u003Cu002Fpu003Eu003Cpu003E } u003Cu002Fpu003Eu003Cpu003E}<u002Fspan> u003Cu002Fpu003Eu003Cpu003E 这样,我觉得就能够明确的反映出这个问题的理解和我们要如何解决如何设计的意图。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E小结u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E相同点:u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E 第一:接口和抽象类都不能被实例化,它们都位于继承树的顶端,用于被其他的类实现和继承。u003Cu002Fpu003Eu003Cpu003E 第二:接口和抽象类都是可以包含抽象方法的,实现接口或是继承抽象类的普通子类都必须实现这些抽象方法。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E不同点:u003Cu002Fstrongu003E u003Cu002Fpu003Eu003Cpu003E 第一:接口只能包含抽象方法,不能包含已经提供实现的方法;抽象类则完全可以包含普通的方法u003Cu002Fpu003Eu003Cpu003E 第二:接口不能定义静态方法;抽象类可以定义静态方法。u003Cu002Fpu003Eu003Cpu003E 第三:接口里面不能够包含初始化块;但是抽象类里面则完全可以包含初始化块u003Cu002Fpu003Eu003Cpu003E 第四:一个类最多只能有一个直接父类,包括抽象类;但是一个类可以直接实现多个接口,通过实现多个接口可以弥补Java中的单继承的不足。u003Cu002Fpu003Eu003Cpu003E 第五:实现抽象类和接口的类必须实现其中的所有方法。抽象类中可以有非抽象方法。接口中则不能有实现方法。u003Cu002Fpu003Eu003Cpu003Eu003Cstrongu003E总结 u003Cu002Fstrongu003Eu003Cu002Fpu003Eu003Cpu003E abstract class 和 interface 是 Java语言中的两种定义抽象类的方式,它们之间存在很大的相似性,都能够实现相应的需求功能,但是对于它们的选择,往往反映出我们对于问题理解和对于设计意图的反映是否正确、合理。同时他们表现的也是两种不同的关系,abstract class表示的是“什么是什么”的一种关系,而interface表示的是“什么像什么”的关系。这就需要我去慢慢总结体会。u003Cu002Fpu003Eu003Cu002Fdivu003E”

原文始发于:「Java学习交流」接口与抽象类的区别

主题测试文章,只做测试使用。发布者:杀手梦三刀,转转请注明出处:http://www.cxybcw.com/27308.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code