Java基础接口和抽象类区别(二)

抽象类

在了解抽象类之前,先来了解一下抽象方法。抽象方法是一种特殊的方法:它只有声明,而没有具体的实现。抽象方法的声明格式为:

抽象方法必须用abstract关键字进行修饰。如果一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰因为抽象类中含有无具体实现的方法,所以不能用抽象类创建对象。

 下面要注意一个问题:在《JAVA编程思想》一书中,将抽象类定义为包含抽象方法的类,但是后面发现如果一个类不包含抽象方法,只是用abstract修饰的话也是抽象类。也就是说抽象类不一定必须含有抽象方法。

从这里可以看出,抽象类就是为了继承而存在的,如果你定义了一个抽象类,却不去继承它,那么等于白白创建了这个抽象类,因为你不能用它来做任何事情。对于一个父类,如果它的某个方法在父类中实现出来没有任何意义,必须根据子类的实际需求来进行不同的实现,那么就可以将这个方法声明为abstract方法,此时这个类也就成为abstract类了

包含抽象方法的类称为抽象类,但并不意味着抽象类中只能有抽象方法,它和普通类一样,同样可以拥有成员变量和普通的成员方法。

注意,抽象类和普通类的主要有三点区别

1)抽象方法必须为public或者protected(因为如果为private,则不能被子类继承,子类便无法实现该方法),缺省情况下默认为public

2)抽象类不能用来创建对象;

3)如果一个类继承于一个抽象类,则子类必须实现父类的抽象方法。如果子类没有实现父类的抽象方法,则必须将子类也定义为为abstract类。

4)抽象类不能被实例化,实例化的工作应该由它的子类来完成,它只需要一个引用即可;

5)抽象方法必须由子类来重写;

6)只要包含一个抽象方法的类比是抽象类,不管是否还包含其他方法;

7)抽象类中可以包含具体的方法,当然也可以不包含抽象方法;

8)子类的抽象方法不能与父类的抽象方法同名;

9abstract不能与final并列修饰同一个类;

10abstract不能与privatestaticfinalnative并列修饰同一个方法;

在其他方面,抽象类和普通的类并没有区别。

接口

接口,英文称作interface,在软件工程中,接口泛指供别人调用的方法或者函数。从这里,我们可以体会到Java语言设计者的初衷,它是(接口是)对行为的抽象。在Java中,定一个接口的形式如下:

接口中可以含有变量和方法。但是要注意,接口中的变量会被隐式地指定为public static final变量(并且只能是public static final变量,用private修饰会报编译错误),而方法会被隐式地指定为public abstract方法且只能是public abstract方法(用其他关键字,比如privateprotectedstaticfinal等修饰会报编译错误),并且接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。从这里可以隐约看出接口和抽象类的区别,接口是一种极度抽象的类型,它比抽象类更加抽象,并且一般情况下不在接口中定义变量。

 要让一个类遵循某组特地的接口需要使用implements关键字,具体格式如下:

可以看出,允许一个类遵循多个特定的接口。如果一个非抽象类遵循了某个接口,就必须实现该接口中的所有方法。对于遵循某个接口的抽象类,可以不实现该接口中的抽象方法。

接口本身就不是一个类。

  1. 抽象类与接口的区别
    1. 语法层面上的区别

1)抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法;

2)抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的;

3)接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法;

4)一个类只能继承一个抽象类,而一个类却可以实现多个接口。

设计层面上的区别

1抽象层次不同。抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象抽象类是对整个类整体进行抽象,包括属性、行为,但是接口却是对类局部(行为)进行抽象。举个简单的例子,飞机和鸟是不同类的事物,但是它们都有一个共性,就是都会飞。那么在设计的时候,可以将飞机设计为一个类Airplane,将鸟设计为一个类Bird,但是不能将 飞行 这个特性也设计为类,因此它只是一个行为特性,并不是对一类事物的抽象描述。此时可以将 飞行 设计为一个接口Fly,包含方法fly( ),然后AirplaneBird分别根据自己的需要实现Fly这个接口。然后至于有不同种类的飞机,比如战斗机、民用飞机等直接继承Airplane即可,对于鸟也是类似的,不同种类的鸟直接继承Bird类即可。

2)跨域不同。抽象类所跨域的是具有相似特点的类,而接口却可以跨域不同的类。我们知道象类是从子类中发现公共部分,然后泛化成抽象类,子类继承该父类即可,但是接口不同。实现它的子类可以不存在任何关系,共同之处。例如猫、狗可以抽象成一个动物类抽象类,具备叫的方法。鸟、飞机可以实现飞Fly接口,具备飞的行为,这里我们总不能将鸟、飞机共用一个父类吧!继承是一个 "是不是"的关系,而 接口 实现则是 "有没有"的关系如果一个类继承了某个抽象类,则子类必定是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比如鸟是否能飞(或者是否具备飞行这个特点),能飞行则可以实现这个接口,不能飞行就不实现这个接口。

3)设计层面不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt Bppt Cppt Bppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt Bppt C进行改动。而辐射式设计,比如某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动

所以说抽象类是自底向上抽象而来的,接口是自顶向下设计出来的

下面看一个网上流传最广泛的例子:门和警报的例子:门都有open( )close( )两个动作,此时我们可以定义通过抽象类和接口来定义这个抽象概念:

但是现在如果我们需要门具有报警alarm( )的功能,那么该如何实现?下面提供两种思路:

1)将这三个功能都放在抽象类里面,但是这样一来所有继承于这个抽象类的子类都具备了报警功能,但是有的门并不一定具备报警功能;

2)将这三个功能都放在接口里面,需要用到报警功能的类就需要实现这个接口中的open( )close( ),也许这个类根本就不具备open( )close( )这两个功能,比如火灾报警器。

 从这里可以看出, Dooropen() close()alarm()根本就属于两个不同范畴内的行为,open()close()属于门本身固有的行为特性,而alarm()属于延伸的附加行为。因此最好的解决办法是单独将报警设计为一个接口,包含alarm()行为,Door设计为单独的一个抽象类,包含openclose两种行为。再设计一个报警门继承Door类和实现Alarm接口。

 网上看到这个总结挺好的

抽象Abstract:在Java程序设计中,利用Abstract关键字来进行抽象,抽象的目的或者说好处,

1.把对象的共性抽取出来,使得代码编写简洁,容易维护。

2.定义一系列规范(方法),继承抽象类的实体类必须满足这些规范(实现抽象方法),这是复杂系统的基础。

3.好的抽象应该就是现实世界的反映,把共性封装成抽象类,但又不存在于现实世界所以不可能实例化。

抽象的实现是通过Abstract修饰抽象类,Abstract修饰方法,或者通过接口来实现。一般都可以认为接口也是一种抽象,只是在使用规则,编程思想上有一些区别,但是他们的目的都是一样的。

  1. abstract Class表示一个类是抽象类,抽象类是不能被实例化的。抽象类里可以只有抽象方法,也可以只有具体方法,或两者兼有。
  2. abstract修饰方法表示一个无实现逻辑的方法。这个就是定义的一个规范,是等着继承类去实现的。
  3. 接口是一种特殊的抽象类,abstract关键字对接口和接口内的方法都是默认存在的(即abstract interface 和interface完全等价)。接口里不能有具体方法。

通过上述三者实现了抽象体系,达到抽象的目的。抽象的使用随处可见,可以分析java.util包,对集合类使用的抽象是很好的例子。


下面列出抽象必须弄清楚的问题:

  1. 抽象方法不可脱离抽象类,或者说,有抽象方法则一个类自动成为抽象类。继承一个抽象类却只部分实现其中的抽象方法,那么这个类也只能还是一个抽象类,直至全部实现。
    反之一个抽象类却可以没有抽象方法,你或许奇怪那这是抽的什么象呢?这种用法还是存在的,其目的是不希望这个类被实例化。这种形式在Spring源码中实现单例模式就用到了。
  2. 抽象类也可以继承实体类,也可以实现接口,没有什么特别的限制。
  3. 抽象方法,接口里的方法,必须被重写实现,所以必须是public的。接口里可以有成员变量,但是必须(默认)是public static final的。
  4. 我们会在抽象类的非抽象方法中看到this。this代表的是对象本身,是和实例化有关的。如果抽象类不能被实例化,那么方法中的this是指什么呢?static方法,抽象方法中肯定不能有this,所以普通方法中的this肯定是由实例化对象调用的,所以这里的this,就是继承抽象类的实体类本身。 ps:实际上在普通类之间的继承,子类调用父类方法时碰到this也是指之类本身。
  5. 抽象类可以是static的(内部类才能使用static),但是抽象方法却不能是static的,因为抽象方法就是为了重写。

我们在什么时候使用抽象类,什么时候使用接口呢?并没有严格的语法规范,根据实际经验来选择。从编程思想上说,结合现实世界,抽象类表明子类和其是一脉相承的,is-a的关系。而接口是表明实现类持有接口的某项功能,has-a的关系。


附带再列出类和接口的一些相互关系,不管是抽象还是实体类都遵从下面的法则:

  1. 接口只能继承(extends)接口,还可以继承多个接口,用逗号分隔。接口不能继承类。
  2. 类只能实现(implements)接口,可以实现多个接口。类可以继承类,只能继承一个类。
原文地址:https://www.cnblogs.com/douyu2580860/p/8289191.html