您的位置:首页 > 编程语言 > Java开发

Java 的抽象特性:抽象类与接口深度解析

2017-08-09 15:05 218 查看
要点:

抽象类

接口

抽象类与接口的差别

一. 抽象

  对于面向对象编程来说,抽象是它的四大特征之中的一个。

在Java中,能够通过两种形式来体现OOP的抽象:接口和抽象类。

接口和抽象类为我们提供了一种将接口与实现分离的更加结构化的方法。



二. 抽象类

1).概念基础

  我们都知道在面向对象的领域一切都是对象。

同一时候,全部的对象都是通过类来描写叙述的,可是并非全部的类都是能够描写叙述对象(对象 = 状态 + 行为)的。假设一个类没有足够的信息来描写叙述一个详细的对象,那么我们就能够将这种类设为抽象类。抽象类仅仅能被public和默认修饰符修饰。

  在了解抽象类之前。先来了解一下 抽象方法抽象方法是一种特殊的方法:它仅仅有声明。而没有详细的实现。

抽象方法的声明格式为:

abstract void func();


  抽象方法必须用abstract关键字进行修饰。假设一个类含有抽象方法,则称这个类为抽象类,抽象类必须在类前用abstract关键字修饰 (特别须要注意的是,抽象类也能够不包括抽象方法,即当中全部的方法都是详细方法)由于抽象类中含有未详细实现的方法。所以不能用抽象类创建对象。

public abstract class ClassName {
abstract void fun();
}


  从这里能够看出。抽象类就是为了继承而存在的,假设你定义了一个抽象类,却不去继承它,那么等于白白创建了这个抽象类。由于你不能用它来做不论什么事情。

对于一个父类,假设它的某个方法在父类中实现出来没有不论什么意义。必须依据子类的实际需求来进行不同的实现,那么就能够将这种方法声明为abstract方法。此时这个类也就成为abstract类了。

  包括抽象方法的类称为抽象类。但并不意味着抽象类中仅仅能有抽象方法,它和普通类一样,相同能够拥有成员变量和普通的成员方法。注意,抽象类和普通类的主要有三点差别:

抽象方法不能是 private的,否则。其不能被子类继承,子类也无法实现该方法。从而这样做没有不论什么意义;

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

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

 在其它方面。抽象类和普通的类并没有差别。

2).本质

抽象类与详细类的唯一差别:含有抽象方法的类一定是抽象类;

抽象类的根本作用是为了继承。所以抽象类的抽象方法不能被private修饰;

抽象类比详细类仅多一点抽象因素:行为层面的抽象(能够包括抽象方法)。

三. 接口

1).概念基础

  接口(interface),在软件project中。接口泛指供别人调用的方法或者函数。从这里。我们能够体会到Java语言设计者的初衷,它是对行为的抽象接口仅仅能被public和默认修饰符修饰。 在Java中。定义一个接口的形式例如以下:

public interface InterfaceName {

}


  接口中能够含有 变量和方法。

可是要注意,接口中的 变量 会被隐式地指定为 public static final变量(而且仅仅能是public static final变量,[b]而且 public static final 可省。即默认就是public static final 的) [/b]。而 方法 会被隐式地指定为 public abstract方法且仅仅能是 public abstract 方法[b](public abstract 可省,即默认就是 public abstract 的)[/b],而且接口中全部的方法不能有详细的实现。也就是说,接口中的方法必须都是抽象方法。

从这里能够隐约看出接口和抽象类的差别。接口是一种极度抽象的类型,它比抽象类更加“抽象”。

  要让一个类遵循某组特地的接口须要使用 implements 关键字,详细格式例如以下:

class ClassName implements Interface1,Interface2,[....]{

}


  能够看出,同意一个类遵循多个特定的接口。假设一个非抽象类遵循了某个接口。就必须实现该接口中的全部方法。对于遵循某个接口的抽象类,能够不实现该接口中的抽象方法。

2).本质

接口是一种行为契约。是对行为的抽象。

四. 接口与抽象类的差别

1.语法层面上的差别

  1)抽象类能够提供成员方法的实现细节。而接口中仅仅能存在 public abstract (可省) 方法;

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

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

  4)一个类仅仅能继承一个抽象类,而一个类却能够实现多个接口。

         


2.设计层面上的差别

  1)抽象类是对一种事物的抽象,即对类抽象,而接口是对行为的抽象。

抽象类是对整个类总体进行抽象。包括属性、行为,可是接口却是对类局部(行为)进行抽象。

举个简单的样例,飞机和鸟是不同类的事物。可是它们都有一个共性,就是都会飞。那么在设计的时候,能够将飞机设计为一个类 Airplane。将鸟设计为一个类 Bird,可是不能将飞行 这个特性也设计为类,因此它仅仅是一个行为特性,并非对一类事物的抽象描写叙述。此时能够将 飞行 设计为一个接口Fly。包括方法fly(),然后Airplane和Bird分别依据自己的须要实现Fly这个接口。然后至于有不同种类的飞机。比方战斗机、民用飞机等直接继承Airplane就可以。对于鸟也是相似的,不同种类的鸟直接继承Bird类就可以。从这里能够看出,继承是一个 “是不是”的关系,而 接口 实现则是 “有没有”的关系。

假设一个类继承了某个抽象类,则子类必然是抽象类的种类,而接口实现则是有没有、具备不具备的关系,比方鸟能否飞(或者是否具备飞行这个特点),能飞行则能够实现这个接口。不能飞行就不实现这个接口。

  2)设计层面不同。抽象类作为非常多子类的父类。它是一种模板式设计。

而接口是一种行为规范(契约),它能够跨越不同的类。是一种辐射式设计。

什么是模板式设计?最简单样例,大家都用过ppt里面的模板,假设用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了。假设它们的公共部分须要修改。则仅仅须要修改模板A就能够了,不须要又一次对ppt B和ppt C进行修改。而辐射式设计,比方某个电梯都装了某种报警器,一旦要更新报警器,就必须全部更新。

也就是说 对于抽象类。假设须要加入新的方法,能够直接在抽象类中加入详细的实现,子类能够不进行变更。而对于接口则不行。假设接口进行了变更,则全部实现这个接口的类都必须进行对应的修改。

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

abstract class Door {
public abstract void open();
public abstract void close();
}


或者

interface Door {
public abstract void open();
public abstract void close();
}


可是如今假设我们须要门具有报警alarm( )的功能,那么该怎样实现?以下提供两种思路:

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

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

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

interface Alram {
void alarm();
}

abstract class Door {
void open();
void close();
}

class AlarmDoor extends Door implements Alarm {
void oepn() {
//....
}
void close() {
//....
}
void alarm() {
//....
}
}


3、小结

抽象类是对一种事物的抽象,接口是对行为的抽象;

抽象类是一种模板,接口是一种契约;

抽象类的抽象程度介于普通类和接口之间。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: