java学习笔记-什么是接口

来源:互联网 发布:gta5pc女角色捏脸数据 编辑:程序博客网 时间:2024/05/17 08:01

接口(interface)是一个比类更加抽象的概念,没接触过面向对象编程(OOP)的人第一眼看代码通常都会懵逼。


如果说类是同一种类似事物的集合,那么接口就是拥有共同特征的一些东西的集合。这些东西可以不是同一种。


打个比方,鸟和飞机都会飞,但是它们显然不是同一种东西,鸟属于动物类的子类,飞机属于交通工具的子类,它们之间根本没任何继承关系,但是“会飞”就是个接口,可以描述它们之间的共性。


用代码描述就是这样:


interface Flyable{void fly();}class Bird extends Animal implements Flyable{public void fly() {//扇翅膀}}class Plane extends Traffic implements Flyable{public void fly() {//发动引擎//助推//滑行//升空}}

interface可以看作一个全是抽象的类,里面只有public abstract方法,这很好理解:当你描述一个公共的特征或者一个行为时,如果它是不可见的(private)那就没有任何意义了。


为什么是abstract呢?用这个例子,“会飞”仅仅是描述了一种共性,但是具体这东西怎么飞,大家各有各的飞法,当然就只能抽象了。当你实现这个接口时,必须重写这个抽象的方法。



再举个例子,比如我家里有水果刀,可以切水果;有剪刀,可以剪纸;有开瓶器,可以开酒瓶。还有个瑞士军刀,可以做上面一切的事情。我应该怎么抽象这些东西呢?


如果不使用接口,我们就只能这样:


class Knives{public void chopFruits() {//切水果}}class Scissors{public void cutPaper() {//剪纸}}class Corkscrews{public void openBottle() {//开瓶盖}}class SwissArmyKnives extends Knives{@Override public void chopFruits() {//重写切水果}}public class House {public static void main(String[] args) {// TODO Auto-generated method stubKnives knife = new Knives();knife.chopFruits();Scissors scissor = new Scissors();scissor.cutPaper();Corkscrews corkscrew = new Corkscrews();corkscrew.openBottle();Knives sak = new SwissArmyKnives();//多态sak.chopFruits(); }}


然后就发现问题了。瑞士军刀也能切水果,那么它是刀子的子类咯?然后瑞士军刀还能干别的呀?怎么办,子类再加两个新的方法:cutPaper和openBottle?


这样抽象,不觉得别扭么?假如我要修改一下剪纸这个方法传入的参数,我是不是两个地方都得改,假如忘记了改瑞士军刀的,是不是程序就挂了?要知道java不允许多继承,瑞士军刀不能既是刀子的子类又是剪刀的子类。


那么假如我抽象一个工具类,里面提供了“切水果”“剪纸”“开瓶盖”三个抽象方法,那么问题又来了,继承抽象类工具时,如果不把这三个方法都实现,就会报错!怎么办?



interface Chopable{void chopFruits();}interface Cutable{void cutPaper();void cutRope();  //新增一个剪绳子方法}interface CanOpen{void openBottle();}class Knives implements Chopable{public void chopFruits() {//切水果}}class Scissors implements Cutable{public void cutPaper() {//剪纸}public void cutRope() {}}class Corkscrews implements CanOpen{public void openBottle() {//开瓶盖}}class SwissArmyKnives implements Cutable, Chopable, CanOpen{@Override public void chopFruits() {//重写切水果}@Override public void cutPaper() {}@Override public void cutRope() {}@Override public void openBottle() {}}public class House {public static void main(String[] args) {// TODO Auto-generated method stubChopable knife = new Knives();knife.chopFruits();Cutable scissor = new Scissors();scissor.cutPaper();CanOpen corkscrew = new Corkscrews();corkscrew.openBottle();Chopable sak = new SwissArmyKnives();//多态sak.chopFruits(); ((Cutable) sak).cutPaper();  //不推荐这么做 ((CanOpen) sak).openBottle();//不推荐这么做 }}

利用接口,我们抽象出了三种特征:“能切”“能剪”“能开瓶”

水果刀和瑞士军刀同时符合能切的特征,它们都实现了切水果功能。

瑞士军刀同时实现了这三个接口,也就是说从三个不同的角度看过去,瑞士军刀是分别拥有三种功能的东西,至于剩下部分是什么样我们并不关心,我们只是想找个顺手的工具来切水果罢了。

同样的,如果我们要给能剪接口加一个方法,比如剪书,剪绳子,剪头发,又或者是改变剪纸的传入参数(极度不推荐这么做,改动旧的方法通常会造成别人或自己的程序报错,应该重载此方法,相当于新增了一个方法)我们需要在改动接口的同时一起修改剪刀类和瑞士军刀类的实现,这样保证了接口的一致性,不会出现改了半拉漏了半拉的情况。

接口通过这种方式,实现了多继承和多态。