面向对象编程
接口Interface
1 接口是什么
1) 接口Interface
,是Java中与类同level的结构,并不是类的成员结构,但接口
直接作用于类。
2) 可以从2方面来理解接口
:
- 从
接口
的角度出发,可以将接口理解为规范具备某种特性的类的定义的标准。
也就是说,接口是对某种特性的标准特征的定义,来限定具有该特性的类的定义。
换句话说,如果一个类设定为具备A特性,那么该类可以通过实现A对应的接口实现该设定。类实现接口,该类就是该接口的实现类,代表着该类具备了该接口的标准特征,实际上与继承的效果一致。 - 从类的角度出发,类与类之间的关系只有继承,不具有继承关系的类之间无法联系起来。但存在这样的情况,我们希望使用或操作具备某种特性的对象,而不局限于特定的某个类,即任何具备该特性的类的对象。
也就是说,具备某种特性的不同的类通过该特性可以被划分为一个整体。
从这个角度,可以将接口理解为不同类都能具有的某种特性的“模板”。而类本身也是一种“模板”,接口可以理解比类更细粒度的作用于类的“模板”。
3) 继承vs接口的实现
- 继承是一个“是不是”的类与类之间的关系。继承具有单继承性,子类只能有一个直接父类。
- 接口是一个“能不能”的类与接口之间的关系。类可以实现多个接口,可以理解为类对接口的实现具有“多重实现性”。
2 接口的定义
1) 接口通过关键字interface
定义,其格式为:interface Name{}
。
2)由于接口作用于类,效果等同于继承,换句话说,一个接口的实现类代表该类具有该接口的一整套结构。因此,接口能定义的结构只可能是类的成员结构。
接口能定义的成员为(JDK7及以前):全局常量即public static final
修饰的量和抽象方法即public abstract
修饰的方法。
由于接口中只能存在全局常量,因此在定义一个接口的“属性”时,可以直接省略public static final
。并且,接口中默认的方法为抽象方法,也就是说定义抽象方法时可以省略public abstract
。
3)理解接口及接口的成员
- 接口本身是
public
的,接口的成员都是public
的。
接口是用于规范类的,其所有结构都作用于类,且不限定为特定的类,因此接口中的成员都是public
的,其本身也是public
的。由于接口本身和其成员只可能是public
的权限,因此在编写对应代码时可以省略public
。 接口中的“属性”都是
static final
的,即全局常量,这些量可以通过接口名.
的方式使用。
接口是作用于类的,类对接口的实现与继承效果一致,也就是说实现类会有对应接口的一整套结构。但抽象类和接口是有区别的,接口中能定义的属性只能是全局常量,本人认为原因在于类主要作用于“对象”,而接口只作用于“类”。
接口的实现
可以类比为类的实例化
:- 类的
实现
就是类的实例化
,一旦类实例化了,该对象存在了一套具有确定内容的对应类的结构。因此实现
可以理解为确定了结构的具体内容
。 - 一个接口的实现类,该类就有一套确定了具体内容的该接口的结构。而类是无法确定一个“变量”的值的,对象在构造时开辟空间时自动确定了所有对应类中的变量的值。因此接口只能有全局常量,这样相当于实现类自动确定了接口的“属性”的值(本质上是直接不需要由类来确定了)。
既然是确定的值,就没必要使类的对象各自都有一份,因此通过
static
来使对应类的对象共享一份即可。- 类的
- 接口中的默认方法是抽象方法
接口本质上是对某种特性的标准的定义,本质上只是一个规范作用,因此默认只确定有什么功能
,而不确定具体的内容
。
一个接口的实现类会有该接口的所有抽象方法,该类要么通过重写这些抽象方法来确定这些方法的具体内容,要么作为抽象类不能构造对象,因为对象无法确定类中的方法的内容。
如果一个接口的实现类为抽象类,此时接口的实现实际上间接由该抽象类的子类去实现,总归还是会被确定内容。这里再次可以理解为什么接口中只能是全局常量:属性是无法被类确定的,因此不存在间接或直接的确定,也就只能在接口中被确定下来。
接口的实现
可以理解为确定具体内容
:
- 对于属性,就是确定值。
- 对于方法,就是确定代码。确定代码并不意味着不依赖于对象,换句话说,确定方法的代码不代表该方法要被
static
。
3 接口的实现
类对接口的实现可以直接理解为继承
,效果完全一样。
实现类会具备对应接口的一整套内容,这套内容中具有的某些限制性结构(比如抽象方法),该类必须遵循对应的限制机制(比如要么重写所有抽象方法,要么作为抽象类)。
一个类对接口的实现的声明用关键字implements
,其格式为:class ClassName implements interface
。
4 接口定义和实现的注意点
1) 一个类可以实现多个接口,在声明时多个接口之间用逗号分隔:class ClassName implements interface1, interface2...
。
2) 一个类若既要声明继承某类,又要声明对接口的实现,语法上规定先声明继承,再声明接口的实现,即先使用关键字extends
,再使用关键字implements
:class ClassName extends SuperName implements interface
。
之所以这样规定,可以理解为,由于类的继承是单继承性,即只会声明一个继承的父类,而接口的实现是可以多实现的,因此类似于“变长”的放到最后,可以理解为便于扩展接口的实现时的书写。
3) 接口与接口之间也可以具备继承关系,用extends
声明,并且能够多继承。
若一个接口继承多个其他接口,用逗号分隔。
接口与接口之间的继承效果与类之间继承效果的一致。
5 接口的使用特性
接口的使用本质上就是对具有某种特性的类的使用,因此接口可以理解为具有某个特性的类。
类的使用体现为其成员的使用,即对象,因此接口的使用也是实现其对象。
1) 接口的使用体现出“多态性”
“多态性”可以理解为:用具有自己直接对象所有特征的非自己直接对象的对象作为自己的对象。
在类的使用中的多态性是指,子类对象可以作为父类的对象。
在接口中的多态性是指,接口无法拥有自己的直接对象(因为没有构造器),其对象只能是其实现类的对象。
2) 接口是一种规范
用“USB接口”来理解接口:
具有USB接口(类比于接口)的产品(类比于类)有鼠标、键盘和U盘等。
这些产品的USB接口有相同规格的形状(类比于接口中定义的全局常量),这才使得它们能够共同用于USB插口,这些产品使用该接口都是用于“传输”的功能(类比于接口中定义的抽象方法),但不同的产品该功能的具体实现内容不同,比如鼠标、键盘主要实现IO的传输,而U盘主要实现存储的传输。
3) 开发中,主要是面向接口编程
这样理解:
- 面向对象编程是指在实现一个系统时,我们将整个系统抽象为多个类,看作是对不同类的对象进行操作,构成整个系统。
- 面向接口编程是指,对共同具有某种特性的不同的类的对象的操作,不是对不同的类单独进行操作,而是抽象出这个共同的特性即为接口,通过对接口操作实现对具有对应特性的对象,不论哪类对象,对应的操作。
如果没有接口,当针对某种特性的对象进行操作时,需要对具有该特性的不同的类分别针对该特性进行操作,也就需要分别编程。
6 接口的匿名实现类的对象
匿名实现类的对象与匿名子类对象定义方式类似,其格式为:new interfaceName(){匿名实现类成员}
。