深切理解 Java 的接口和笼统类

发布日期:2019-07-23 19:43:03 阅读数: 85次 来源: 作者:

对于面向对象编程来说,笼统是它的一大特征之一。在 Java 中,能够通过两种形式来表现 OOP 的笼统:接口和笼统类。这两者有太多类似的处所,又有太多分歧的处所。良多人在初学的时候会认为它们能够随便交换利用,可是现实则否则。今天我们就一路来进修一下Java中的接口和笼统类。


一、笼统类

在领会笼统类之前,先来领会一下笼统方式。笼统方式是一种特殊的方式:它只要声明,而没有具体的实现。笼统方式的声明格局为:

abstract void fun();

笼统方式必需用 abstract 环节字进行润色。若是一个类含有笼统方式,则称这个类为笼统类,笼统类必需在类前用 abstract 环节字润色。由于笼统类中含有无具体实现的方式,所以不克不及用笼统类建立对象。

下面要留意一个问题:在《JAVA 编程思惟》一书中,将笼统类定义为"包含笼统方式的类",可是后面发觉若是一个类不包含笼统方式,只是用 abstract 润色的话也是笼统类。也就是说笼统类纷歧定必需含有笼统方式。小我感觉这个属于钻牛角尖的问题吧,由于若是一个笼统类不包含任何笼统方式,为何还要设想为笼统类?所以暂且记住这个概念吧,不必去深究为什么。

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

从这里能够看出,笼统类就是为了承继而具有的,若是你定义了一个笼统类,却不去承继它,那么等于白白建立了这个笼统类,由于你不克不及用它来做任何工作。对于一个父类,若是它的某个方式在父类中实现出来没有任何意义,必需按照子类的现实需求来进行分歧的实现,那么就能够将这个方式声明为 abstract 方式,此时这个类也就成为 abstract 类了。

包含笼统方式的类称为笼统类,但并不料味着笼统类中只能有笼统方式,它和通俗类一样,同样能够具有成员变量和通俗的成员方式。留意,笼统类和通俗类的次要有三点区别:

  • 1)笼统方式必需为 public 或者 protected(由于若是为 private,则不克不及被子类承继,子类便无法实现该方式),缺省环境下默认为 public。
  • 2)笼统类不克不及用来建立对象;
  • 3)若是一个类承继于一个笼统类,则子类必需实现父类的笼统方式。若是子类没有实现父类的笼统方式,则必需将子类也定义为为 abstract 类。
  • 在其他方面,笼统类和通俗的类并没有区别。 亚博手机app

二、接口

接口,英文称作 interface,在软件工程中,接口泛指供别人挪用的方式或者函数。从这里,我们能够体味到 Java 言语设想者的初志,它是对行为的笼统。在 Java 中,定一个接口的形式如下:

[public] interface InterfaceName {
 
}

接口中能够含有 变量和方式。可是要留意,接口中的变量会被隐式地指定为 public static final 变量(而且只能是 public static final变量,用 private 润色会报编译错误),而方式会被隐式地指定为 public abstract 方式且只能是 public abstract 方式(用其他环节字,好比 private、protected、static、 final 等润色会报编译错误),而且接口中所有的方式不克不及有具体的实现,也就是说,接口中的方式必需都是笼统方式。从这里能够模糊看出接口和笼统类的区别,接口是一种极端笼统的类型,它比笼统类愈加"笼统",而且一般环境下不在接口中定义变量。

要让一个类遵照某组特意的接口需要利用 implements 环节字,具体格局如下:

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

能够看出,答应一个类遵照多个特定的接口。若是一个非笼统类遵照了某个接口,就必需实现该接口中的所无方法。对于遵照某个接口的笼统类,能够不实现该接口中的笼统方式。


笼统类和接口的区别

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(); }

可是此刻若是我们需要门具有报警 的功能,那么该若何实现?下面供给两种思绪:

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() { //.... } }
本文由亚博手机app编辑整理亚博手机app