首页 > 应用开发 > > JAVA中的接口和抽象类有什么区别?
一. 什么是抽象类
只要满足被abstract 类修饰的类就是一个抽象类。
也就是说,抽象类可以没有抽象方法,可以没有任何一个抽象方法。
一个类要是有抽象方法那么这个类就必须是一个抽象类,即被abstract 修饰。
也就是说抽象类只是比普通类多了一个abstract 关键字,即不能创建对象,还有写不写抽象方法的选择 , 成员变量,构造方法等等它都可以有。
但是大多数情况下抽象类是都会有抽象方法的,比如JDK 中的 AbstractMap ,抽象类设计主要是为了把共性的东西让子类去继承(成员变量和成员方法) , 把包含子类特性的方法定义成抽象的,让子类自己去发挥。
抽象类不能创建实例,它只能作为父类被继承。抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象。从多个具有相同特征的类中抽象出一个抽象类,以这个抽象类作为其子类的模板,从而避免了子类的随意性。
(1) 抽象方法只作声明,而不包含实现,可以看成是没有实现体的虚方法
(2) 抽象类不能被实例化
(3) 抽象类可以但不是必须有抽象属性和抽象方法,但是一旦有了抽象方法,就一定要把这个类声明为抽象类
(4) 具体派生类必须覆盖基类的抽象方法
(5) 抽象派生类可以覆盖基类的抽象方法,也可以不覆盖。如果不覆盖,则其具体派生类必须覆盖它们
在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就可以称之为抽象类。
1. 抽象方法:使用 abstract 修饰且没有方法体的方法。
特点:
① 抽象方法没有方法体,交给子类实现
② 抽象方法修饰符不能是 private final static
③ 抽象方法必须定义在抽象类或者接口中
2. 抽象类:包含抽象方法的类,即使用 abstract 修饰的类。
特点:
① 抽象类不能被实例化,只能被继承
② 抽象类中可以不包含抽象方法(不包含抽象方法就没有太大意义,可以作为工具类防止被实例化)
③ 抽象类的子类可以不实现该类所有的抽象方法,但也必须作为抽象类(抽象派生类)
④ 抽象类的构造方法不能定义成私有(子类构造方法会调用父类构造方法)
⑤ 抽象类不能使用 final 修饰, final 修饰的类不能被继承
实例:武器作为一个抽象类具备攻击行为(attack 方法),具体如何攻击( how2Attack 方法)需要子类实现。如:机关枪可以射击敌人,可以丢向敌人
public class Test3 {
public static void main(String[] args) {
Gun gun = new Gun(" 机关枪 ");
Grenade grenade = new Grenade(" ");
gun.attack();
grenade.attack();
gun.how2Attack();
grenade.how2Attack();
}
}
abstract class Weapon{
String name;
public void attack(){
System.out.println(name+" 具有攻击行为 ");
}
abstract void how2Attack();
}
class Gun extends Weapon{
public Gun(String name) {
this.name = name;
}
@Override
void how2Attack() {
System.out.println(name+" 射击敌人 ");
}
}
class Grenade extends Weapon{
public Grenade(String name){
this.name = name;
}
@Override
void how2Attack() {
System.out.println(name+" 丢向敌人 ");
}
二 . 什么是接口?
广义的接口:对外提供规则的就是接口
java 中的接口就是 interface 修饰的一个结构。
接口中的成员变量的缺省属性是static final
JDK1.8 之前接口中的方法必须是抽象方法 , 即没有方法体, JDK1.8 中的接口可以有 default 修饰的方法,有方法体。
(1) 接口不能被实例化
(2) 接口只能包含方法声明
(3) 接口的成员包括方法、属性、索引器、事件
(4) 接口中不能包含常量、字段 ( 域 ) 、构造函数、析构函数、静态成员
default 修饰的方法有什么特点?
1. 因为接口不能被实例化,所以 default 方法跟普通方法没有什么区别,只是普通方法是父类提供给子类去直接使用的,默认方法是接口的方法是提供给实现它的类去使用的。
2. 如果一个类实现了俩个接口,俩个接口中都有相同名称的 default 方法,那么编辑器就会提示你俩个接口中的默认方法重复了,推荐你去重写自己的方法,或者在重写方法中用 接口名 .super. 方法名()指定调用哪一个
3. 如果一个类实现了多个同名的 default 方法的接口的同时,又继承了另一个有同名方法的类,那么编辑器就不会报错了,一定会调用类中的同名方法,因为继承的优先级高,简单来理解的话,我们在写代码时候也是先写 extends 再写 implements 的,不然编辑器就会报错。
1. 什么是接口:
① 硬件接口:是指同一计算机不同功能层之间的通信规则称为接口。
② 软件接口:是指对协定进行定义的引用类型。其他类型实现接口,以保证它们支持某些操作。
2.Java 中的接口:在 JAVA 编程语言中是接口一个抽象类型,是抽象方法的集合,接口通常以 interface 来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
特点:
① 接口中没有构造器,不能被实例化
② 接口只能继承接口,不能继承类,接口支持多继承
③ 接口中的定义的成员变量,默认是 public static final 修饰的静态常量
④ 接口中定义的方法,默认是 public abstract 修饰的抽象方法
⑤ 接口中定义的内部类,默认是 public static 修饰的静态内部类
标志接口:仅仅作为一个定义,就是一个标志
常量接口:用来封装多个常量信息
注意:在JDK8 中,接口也可以定义静态方法和默认非静态方法,可以直接用接口名调用静态方法,实现类可以调用默认非静态方法。如果同时实现两个接口,接口中定义了一样的默认方法,则实现类必须重写默认方法,不然会报错。
实例:走路和游泳作为两个抽象的行为,青蛙可以实现两个行为接口来具体实现行为的内容
public class Test4 {
public static void main(String[] args) {
Frog frog = new Frog(" 青蛙 ");
frog.getName();
frog.work();
frog.swim();
}
}
class Animal {
String name;
public String getName() {
System.out.println("Animal:"+name);
return name;
}
public void setName(String name) {
this.name = name;
}
}
interface IWalk{
void work();
}
interface ISwim{
void swim();
}
class Frog extends Animal implements IWalk,ISwim{
public Frog(String name) {
this.name = name;
}
@Override
public void work() {
System.out.println(this.name+": 蹦蹦跳跳地走路 ");
}
@Override
public void swim() {
System.out.println(this.name+": 在水里蛙泳 ");
}
三 . 抽象类和接口的区别
1. 抽象类只能被类继承,接口既可以被接口继承,也能被类实现。
2 抽象类中成员变量想定义什么样就定义成什么样, . 接口中的成员变量只能是 staic final 的。
3. 抽象类可以有抽象方法和成员方法和构造方法,接口中只能有抽象方法或者 default 方法。
4. 从设计思想上来说,抽象类是就是用来被继承的,主要是提供共性的功能,强调这个类是什么,接口中主要是提供扩展功能,强调这个类又多了一些功能,举一个例子,比如有一个抽象类是动物类,猫类如果实现了动物类,那么就有了动物的共性功能,如果有一个接口是和人聊天的接口,里面有一个方法是和人聊天的抽象方法,如果猫类实现了这个接口,即重写了和人聊天的方法,等于说猫学会了和人聊天(扩展)。
(1 )抽象类可以有构造方法,接口中不能有构造方法。
(2 )抽象类中可以有普通成员变量,接口中没有普通成员变量
(3 )抽象类中可以包含静态方法,接口中不能包含静态方法
(4 ) 一个类可以实现多个接口,但只能继承一个抽象类。
(5 )接口可以被多重实现,抽象类只能被单一继承
(6 )如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽象类的子类中实现接口中方法
四. 抽象类和接口的异同点
1. 语法层面
相同点:
① 抽象类和接口都不能被实例化
② 抽象类和接口都可以定义抽象方法,子类 / 实现类必须覆写这些抽象方法
(1) 都可以被继承
(2) 都不能被实例化
(3) 都可以包含方法声明
(4) 派生类必须实现未实现的方法
不同点:
① 抽象类有构造方法,接口没有构造方法
② 抽象类可以包含普通方法,接口中只能是 public abstract 修饰抽象方法( Java8 之后可以)
③ 抽象类只能单继承,接口可以多继承
④ 抽象类可以定义各种类型的成员变量,接口中只能是 public static final 修饰的静态常量
2. 设计层面
① 抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类 Airplane ,将鸟设计为一个类 Bird ,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口 Fly ,包含方法 fly( ) ,然后 Airplane 和 Bird 分别根据自己的需要实现 Fly 这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承 Airplane 即可,对于鸟也是类似的,不同种类的鸟直接继承 Bird 类即可。从这里可以看出,继承是一个 " 是不是 " 的关系,而 接口 实现则是 " 有没有 " 的关系。如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。
② 设计层面不同,抽象类作为很多子类的父类,它是一种外汇返佣http://www.fx61.com/模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过 ppt 里面的模板,如果用模板 A 设计了 ppt B 和 ppt C , ppt B 和 ppt C 公共的部分就是模板 A 了,如果它们的公共部分需要改动,则只需要改动模板 A 就可以了,不需要重新对 ppt B 和 ppt C 进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。
1 、概念不一样。接口是对动作的抽象,抽象类是对本质的抽象。
抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它。
所以,在高级语言上,一个类只能继承一个类(抽象类)( 正如人不可能同时是生物和非生物 ) ,但是可以实现多个接口 ( 吃饭接口、走路接口 ) 。
2 、使用不一样:
a. 抽象类 和 接口 都是用来抽象具体对象的 . 但是接口的抽象级别最高
b. 抽象类可以有具体的方法 和属性 , 接口只能有抽象方法和不可变常量
c. 抽象类主要用来抽象类别 , 接口主要用来抽象功能 .
d. 抽象类中,且不包含任何实现,派生类必须覆盖它们。接口中所有方法都必须是未实现的。
e. 接口是设计的结果 ,抽象类是重构的结果
3 、使用方向:当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。
注意:抽象类的功能要远超过接口,但是,定义抽象类的代价高。因为高级语言来说(从实际设计上来说也是)每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度的。
五. 抽象类和接口的使用场景
1. 抽象类的使用场景
既想约束子类具有共同的行为(但不再乎其如何实现),又想拥有缺省的方法,又能拥有实例变量
如:模板方法设计模式,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中某些步骤的具体实现。
2. 接口的应用场景
① 约束多个实现类具有统一的行为,但是不在乎每个实现类如何具体实现
② 作为能够实现特定功能的标识存在,也可以是什么接口方法都没有的纯粹标识。
③ 实现类需要具备很多不同的功能,但各个功能之间可能没有任何联系。
④ 使用接口的引用调用具体实现类中实现的方法(多态)
抽象性和具体性都是相对的,不是绝对的。简单说,概念的内涵越小,则其抽象程度就越高,其外延也越大,反之亦然。比如“人”比“男人”抽象一点,而“生物”又比“人”更抽象一点,“物质”则比“生物”更抽象。
抽象的概念是由具体概念依其“共性”而产生的,把具体概念的诸多个性排出,集中描述其共性,就会产生一个抽象性的概念。抽象思维,是人类思维达到高级阶段产生的一种能力,例如,当小孩子思维尚未成熟时,他们只能掌握具体概念,他们在学习代词“你、我、他”时往往遇到困难,因为代词具有较高的抽象性。
总之,抽象概念的外延大,内涵小,具体概念的外延小,内涵大。
六. 抽象类与普通类的区别
1 、普通类可以去实例化调用;抽象类不能被实例化,因为它是存在于一种概念而不非具体。
2 、普通类和抽象类都可以被继承,但是抽象类被继承后子类必须重写继承的方法,除非自类也是抽象类。
public class Pet {
public void play(){ // 这是宠物类 , 普通父类,方法里是空的
}
}
--------------------------
public class Cat extends Pet { // 这是子类,是一个猫类 , 重写了父类方法
public void play(){
System.out.println(" 猫爬树 ");
}
}
------------------------
public class Dog extends Pet { // 这是子类,是一个狗类 , 重写了父类方法
public void play(){
System.out.println(" 狗啃骨头 ");
}
}
-------------------------
public class Test {
public static void main(String[] args) { // 这是测试类,分别调用了子类的不同方法
Pet p1=new Dog(); // 多典型的多态表现啊,相当的给力
Pet p2=new Cat();
p1.play();
p2.play();
}
}
输出结果:
狗啃骨头
猫爬树
问题:把父类改成抽象类,方法改成抽象方法,那么
public void play();// 抽象方法没方法体
子类不变,依然重写父类方法,那这个跟普通父类没区别啊?
难道说就一个抽象方法没方法体就完事了??那我普通方法有方法体,我空着不写内容不就得了,不跟抽象方法一个样吗??
别跟我说抽象类还不能实例化,哥也不需要去new 它!
普通类都能搞定的,还弄个抽象类有什么意义?我前面都说了普通类的方法我可以空着不写,达到跟抽象类方法没方法体一样的效果。
既然两种方式都能达到同一个输出效果,弄一种方式不就得了,那为什么还要创造出一个抽象类出来?难道是比普通类看着舒服?用着爽?还是更加便捷?还是为了强制让别人用的时候必须强制化实现抽象方法省的你忘了什么的?
答:就是为了强制不能实例化,以及强制子类必须实现方法这不是你忘不忘的问题
你说你不去new 它就行了,这话没错
那你想另一个问题,为什么要有访问控制呢?为什么要有private 和 public 之分呢?
我可以全部public ,不该访问的,我不访问就行了啊
小程序里,看不出什么区别,反而private 成员要写一堆 set 和 get 函数,多麻烦,我自己写小程序的时候也会偷懒全部 public
但是项目大了,代码多了,这种严谨的结构就很重要了
且不说会有很多人合作一起写一个程序,哪怕还是你一个人写,也保不住有忘记的时候,那时候编译器不报错,茫茫码海上哪找错误去
面向对象说到底就是方便你思考,模块化,易维护管理,硬要说没必要,整个面向对象都没必要了,C 语言有什么干不了的呀,运行效率还高。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69927062/viewspace-3162305/ ,如需转载,请注明出处,否则将追究法律责任。