浅析Java抽象类与接口的区别

2018-01-08 22:34曾裕宗
电脑知识与技术 2017年36期
关键词:接口继承实现

曾裕宗

摘要:抽象是Java语言的一种很重要的特性,可以通过两种形式来体现:abstract class(抽象类) 和interface(接口)。两者之间有很大的相似性,但也存在不一样的地方,该文结合笔者多年Java开发和教学经验,先分别阐述抽象类、接口,接着剖析两者之间的区别,然后给出一个案例来说明,最后做出总结。

关键词:抽象类;接口;继承;实现;区别

中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2017)36-0202-02

抽象是任何一门面向对象编程语言的一种相当重要的特性,Java亦如此。Java OOP的抽象包含兩种:abstract class(抽象类) 和interface(接口)。从某种意义上讲,正是因为有了这两种抽象机制,Java才具备强大的 面向对象能力。它们两者之间有很大的相似性,在编程的时候,有时可以相互替换实现,但肯定也存在不一样的地方,否则Java就没必要搞两个概念机制了。本文结合笔者多年Java开发和教学经验,来剖析、阐述两者之间的区别,试图给众多Java初学者提供一些借鉴和参考。

首先,我们来讲抽象类。简单来说,包含抽象方法的类就叫抽象类。这里所说的抽象方法,是指只有方法头部,即方法名称,但没有最重要的方法实现的语句体,其定义格式为:

从定义中,我们看出:抽象类所包含的方法,可以是抽象方法,也可以是普通的实现方法,另外,抽象类也可以拥有成员变量(属性)。当然,它跟普通类还是有以下的区别:

1) 抽象类,其修饰符必须为public或者protected,不能是private,因为创建抽象类,就是要被其他类继承,用private修饰了,则不能被子类继承,子类便无法实现该方法。

2) 抽象类不能用来创建对象,即抽象类不能被直接实例化,要通过其普通子类进行实例化。

3) 如果一个普通子类继承于一个抽象父类,则该类一定要重写实现该父类的抽象方法。如果该子类仍然是一个抽象类,这也是允许的,就不必重写实现该父类的抽象方法,但必须用abstract修饰。

接着,我们来讲接口。接口,也可以认为是一种特殊的抽象类,当然,它本质上不是类,它是一些方法特征的集合,但不可以有方法的实现。接口全部是由全局变量和公共的抽象方法组成,接口中的所有方法都是抽象方法,而且其修饰符必须是public类型,其定义格式为:

从定义中,我们看出:接口可以有全局成员变量,是一种超级抽象的类型,它比抽象类更加“抽象”。显然,我们不能直接通过接口来创建对象,而是要创建普通类,先实现接口,再通过普通类来创建对象,其语法定义:

从定义中,我们看出:普通类可以实现多个接口,再就是,如果是普通类实现接口,那么必须重写实现接口中的所有方法;如果实现接口的还是抽象类,则可以不必重写实现接口中的所有方法,还可以有自己的方法。

讲完了抽象类和接口,我们重点来论述两者之间的区别,总体来说,有两大方面的区别:

1 定义的语法不同

从定义中,我们看出:两者的关键词不同,抽象类是abstract class,而接口是Interface;抽象类可以有成员变量数据,也可以具有非抽象方法,但是接口则不同,它方法外只能定义的是常量(一般情况下不定义),而且它所有的方法都必须是抽象的。可以这么理解,接口是特殊的抽象类。子类只能继承一个父类或抽象类,但是它却可以实现多个接口,这叫子类的单继承、多实现。

2 设计理念层次不一样

1) 抽象级别不一样,抽象类是对整体类的抽象,包含属性和方法;而接口是对其中方法的抽象,即一般只是对其方法进行抽象。

2) 实现类的范围不同,抽象类,其实是从子类中提取共性部分,然后抽象出来,反之,子类继承该父类就可以了,也就是说里面的抽象方法一般来自同一个类别,而接口却可以跨越不同的类,实现它的子类可以不存在任何关系和共同之处,即接口中定义的抽象方法,在被不同的普通类实现时,即重写其抽象方法时,可以具有完全不同的行为,即语句体可以完全不同。举个例子,老虎、牛这些动物,来自同一类别,可以抽象成一个动物类,都有睡的行为;鸟、飞机都能飞,可以有Fly接口,但是,显然它们是没有共同父类的?所以,只能用接口写。也就是说,抽象类反映的是一种继承关系,父类和子类之间必须存在"is-a" 关系,而接口则不同,其同样的方法,在不同的地方,可以实现完全不一样的行为,体现的是"like-a"关系。

3) 设计方式不同,抽象类是要先有子类,然后才抽象出父类,是一种从下往上的构建法则;而接口不需要先有子类,它只需要定义一些抽象方法就行。比如前面提到的例子,假如我们只有一个老虎类,你肯定不能马上抽象成一个动物类,最起码还要有牛类,然后才可以找它们的共同点,形成一个动物抽象类,它是倒过来实现的。但是接口不一样,比如前面提到的飞,我们只需要事前定义好飞的行为接口,其后面的实现不管它,可以有完全不同的行为,也就是说,接口是从上向下设计出来的。

问题来了,假如再增加一个fly( )的功能,该怎么实现?

可以这么解决,将这个方法,连同之前的两个方法,一起放在抽象类里,但这样做有个问题,继承于这个抽象类的子类都带上了fly( )行为,但现实中,有些动物是不会飞的;也可以将这三个方法都放在接口里,但这样一来,有些只有飞功能的类就又不得不去实现这个接口中的eat( )和sleep( )方法,比如飞机,它没有eat( )和sleep( )方法。所以,这个解决办法不妥,最合理的解决方案是,应该将飞创建为一个接口,具有fly()行为,而把Animal创建为一个抽象类,它具有eat和sleep两种方法。最后,创建一个类继承Animal抽象类和实现Fly接口,这样问题就科学的解决了,改进后的代码如下:

综上所述,Java抽象类与接口的区别,主要有以下5个方面:

1) 抽象类是特殊的类,它只能被继承一次,而接口可以被多次实现,这就是单继承、多实现。

2) 在抽象类中,其方法可以是抽象方法,也可以是实现方法,可以有全局成员变量;接口只能有抽象方法,只能有常量,且一般情况下不定义它。

3) 抽象类与接口,它们的设计理念不同。抽象类反映的是"is-a"关系,接口反映的是"like-a"关系。

4) 接口中定义的变量是public static final 型,且一定要赋初始值,它相当于一个常量,故实现类中不能再次定义,也就不能改变它的值。

5) 抽象类中定义的变量是普通的,它就是一个真正的变量,它的值可以在子类中再次定义,也可以重新赋值。

参考文献:

[1] 徐红.java程序设计.高等教育出版社,2013.

[2] 廖大强.面向多目标的云计算资源调度算法,计算机系统应用,2016,25(2):180-189.

猜你喜欢
接口继承实现
某电站工程设计管理与施工、质量控制接口关系研究
办公室人员尚需制定个人发展规划
浅谈杜审言、杜甫的祖孙关系:推崇、继承、发展
浅析铁路通信传输的构成及实现方法