• Java接口


    接口(英文:Interface)是Java中非常重要的内容,初学的时候可能感受不深,但是在做项目的时候,对面向接口编程的运用就变得尤为重要,不过这是后话了。现在先讨论假如是刚刚接触接口这个概念,该怎么玩?如果是看过我之前文章的朋友应该了解,在遇到一个新概念的时候,我一般思考框架是先问下面三个问题:

    1.这个东西有什么用?用来干什么的?它的意义在哪里?(显然,如果是没用的东西,就没必要浪费时间了;其实,弄懂了这个问题,就掌握了50%)

    2.这个概念或者技能点怎么用?也就是它的表现形式,如关键字、修饰词、语法什么的。。。(这个占20%)

    3.这个东西在用的过程中,有哪些关键点和细节点?(这个占30%)

    上面三个问题搞清楚了,剩下的就是去用了。。。“无他,但手熟尔。”

    一、接口有什么用?它的意义在哪里?

    回答这个问题,两句话就够了:

    1.接口表示一种能力;

    2.接口表示一种约定。

    先来看第一点“接口表示一种能力”,举个栗子:

    需求:现在要创造一个蜘蛛侠。人有“唱歌”和“考试”的功能,蜘蛛有“爬行”和“吐丝”的功能。

    分析:首先蜘蛛侠是一个人,他有蜘蛛的能力。按照面向对象思想,可以将人和蜘蛛分别定义成抽象类。但是,不能让蜘蛛侠在继承人的同时又继承蜘蛛。两个原因:一、蜘蛛侠不是蜘蛛,不符合继承中 【is a】的关系;二、Java只支持单继承。如何解决这个问题呢?这时就要用到接口,接口是【has a】的关系。可以将蜘蛛的行为能力定义为接口,让蜘蛛侠继承人,实现蜘蛛的行为能力的接口。实现代码如下:

    1 public abstract class Person { //定义Person抽象类

    2 public abstract void sing(); //唱歌抽象方法

    3 public abstract void exam(); //考试抽象方法

    4 }

    5 public interface ISpiderable { //定义一个蜘蛛的行为能力接口

    6 public abstract void creep(); //爬行抽象方法

    7 public abstract void shootWeb(); //吐丝抽象方法

    8 }

    9 public class SpiderMan extends Person implements ISpiderable{//继承人,实现蜘蛛的行为能力接口

    10 String name = "彼得·帕克";

    11

    12 @Override

    13 public void creep() { //实现爬行方法

    14 System.out.println(name + " 在屋顶上爬,在树枝上爬,在夕阳下的草地上爬。。。");

    15 }

    16 @Override

    17 public void shootWeb() { //实现吐丝方法

    18 System.out.println(name + " 吐丝织网抓虫子");

    19 }

    20 @Override

    21 public void sing() { //实现唱歌方法

    22 System.out.println(name + " 往事不要再提人生已多风雨~");

    23 }

    24 @Override

    25 public void exam() { //实现考试方法

    26 System.out.println(name + " 上午考语文,下午考数学,明天考英语。。。");

    27 }

    28 }

    29 public class Test { //测试一下

    30 public static void main(String[] args) {

    31 SpiderMan spiderman = new SpiderMan();

    32 spiderman.creep();

    33 spiderman.sing();

    34 }

    35 }

    运行结果如下:

    接着来,有天傍晚蜘蛛侠吃饱了没事儿闲溜达,在路边草丛里发现了雷神的大铁锤,于是他有具备了闪电的能力:

    1 public interface ILightningable { //定义闪电能力接口

    2 public abstract void lightning(); //闪电抽象方法

    3 }

    4 public class SpiderMan extends Person implements ISpiderable,ILightningable{//继承人,实现蜘蛛的行为能力接口,实现闪电能力接口

    5 String name = "彼得·帕克";

    6

    7 @Override

    8 public void creep() { //实现爬行方法

    9 System.out.println(name + " 在屋顶上爬,在树枝上爬,在夕阳下的草地上爬。。。");

    10 }

    11 @Override

    12 public void shootWeb() { //实现吐丝方法

    13 System.out.println(name + " 吐丝织网抓虫子");

    14 }

    15 @Override

    16 public void sing() { //实现唱歌方法

    17 System.out.println(name + " 往事不要再提人生已多风雨~");

    18 }

    19 @Override

    20 public void exam() { //实现考试方法

    21 System.out.println(name + " 上午考语文,下午考数学,明天考英语。。。");

    22 }

    23 @Override

    24 public void lightning() {

    25 System.out.println(name + " 来一波闪电~"); //实现闪电方法

    26 }

    28 public class Test { //测试一下

    29 public static void main(String[] args) {

    30 SpiderMan spiderman = new SpiderMan();

    31 spiderman.creep();

    32 spiderman.sing();

    33 spiderman.lightning();

    通过上面的例子,“接口表示一种能力”已经算是不言而喻了,那么,为什么说“接口表示一种约定”?

    首先,什么是“约定”?所谓的约定就是,这事儿就按咱哥俩说的规矩办,谁也别出幺蛾子。举个经典的打印机的例子:要求实现打印机的打印功能。打印机的墨盒可能是彩色的,也可能是黑白的,所用的纸张可以有多种类型,如A4、B5等,要命的是墨盒和纸张都不是打印机厂商生产的。那么,打印机厂商如何避免自的打印机与市场上的墨盒、纸张不符呢?

    分析:有效解决该问题的途径是制定墨盒、纸张的约定或标准,然后打印机厂商按照约定对墨盒、纸张提供支持,这样一来,无论最后使用的是厂商张三还是厂商王麻子提供的墨盒或纸张,只有符合统一的约定,打印机都可以打印。当然,“接口(Interface)”就是这样一种约定。打印机打印功能实现如下:

    1 public interface IInkBox { //定义墨盒接口,约定墨盒的标准

    2 public String getColor(); //返回墨盒的颜色

    4 public interface IPaper { //定义纸张的接口,约定纸张的标准

    5 public String getSize();//返回纸张的种类

    6 }

    7 public class Printer{ //定义打印机类,引用墨盒接口、纸张接口实现打印功能

    8 IInkBox inkbox=null;

    9 IPaper paper=null;

    10 public Printer(IInkBox inkbox,IPaper paper) { //构造函数,以接口类型为形参实现多态

    11 this.inkbox = inkbox;

    12 this.paper = paper;

    13 }

    14 public void printer() { //实现打印功能

    15 System.out.println("使用"+inkbox.getColor()+"墨盒在"+paper.getSize()+"纸张上打印。");

    16 }

    17 }

    18 public class ColorInkBox implements IInkBox{ //墨盒厂商按照墨盒接口实现彩色墨盒ColorInkBox类

    19 public String getColor() {

    20 return "彩色";

    21 }

    23 public class GrayInkBox implements IInkBox{ //墨盒厂商按照墨盒接口实现黑白墨盒GrayInkBox类

    24 public String getColor() {

    25 return "黑白";

    28 public class A4Paper implements IPaper{ //A4纸类实现纸张接口

    29 public String getSize() {

    30 return "A4纸";

    31 }

    32 }

    33 public class B5Paper implements IPaper{ //B5纸类实现纸张接口

    34 public String getSize() {

    35 return "B5纸";

    36 }

    37 }

    38 public class Test { //测试一下

    39 public static void main(String[] args) {

    40 IInkBox colorInk = new ColorInkBox(); //接口IInk类型引用指向彩色墨盒ColorInkBox实现类的对象,多态

    41 IInkBox grayInk = new GrayInkBox();

    42 IPaper a4Paper = new A4Paper(); //接口IPaper类型引用指向A4纸A4Paper实现类的对象,多态

    43 IPaper b5Paper = new B5Paper();

    44

    45 Printer printer = new Printer(colorInk,a4Paper); //创建Printer对象(组装打印机),彩色墨盒、A4纸

    46 printer.printer();

    47 Printer printer2 = new Printer(grayInk,b5Paper); //创建Printer对象(组装打印机),黑白墨盒、B5纸

    48 printer2.printer();

    49 }

    50 }

    功能实现,这就是“接口表示一种约定”。

    二、接口怎么用?它的表现形式?

    其实,从上面的例子中聪明的你肯定已经大致知道接口怎么用了,下面就总结一下Java中接口的定义语法和类实现接口的语法如下:

    [修饰词] interface 接口名 extends 父接口1,父接口2,....{

    //常量定义

    //抽象方法定义

    }

    class 类名 extends 父类名 implements 接口1,接口2,...{

    //类成员

    【关于接口用法的说明(其实,初学时不用都记住,先掌握关键点用起来再说,报几次错再回来补细节)】:

    1.如果修饰词是public,则该接口在整个项目中可见;如果省略修饰词,则该接口只在当前包中可见。

    2.接口中只能定义常量。接口中的属性都会自动用 public static final 修饰,即接口中的属性都是全局静态常量,必须在定义时指定初始值。

    3.接口中所有方法都是抽象方法,都会自动用 public abstract 修饰,即接口中只有全局抽象方法。

    4.接口之间可以通过extends实现继承关系,一个接口可以继承多个接口,但接口不能继承类。

    5.接口的实现类必须实现接口的全部方法,否则就变成了抽象类。

    三、接口使用的关键点?

    了解接口很重要的一点就是它和抽象类的区别,这两个东西确实很像,都有继承,都有抽象方法,有种不严谨的说法甚至说“可以把接口当作一种极端的抽象类”,这么说有一定道理,但是接口和抽象类还是有很大的不同:

    【语法方面】:

    1.抽象类中属性可以有常量、变量,接口中只能是 public static final 修饰的常量;

    2.抽象类中方法可以有抽象方法、普通成员方法,接口中只能有抽象方法;

    3.抽象类只能单继承,接口可以继承多个接口;

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

    【设计方面】:

    1.抽象类是对事物的抽象,接口是对行为的抽象。就像上面蜘蛛侠的例子,抽象类 Person 是抽象人这个事物,接口 ISpiderable 是抽象蜘蛛的行为能力。

    2.设计模式不同,抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。什么是模板式设计?最简单例子,大家都用过ppt里面的模板,如果用模板A设计了ppt B和ppt C,ppt B和ppt C公共的部分就是模板A了,如果它们的公共部分需要改动,则只需要改动模板A就可以了,不需要重新对ppt B和ppt C进行改动。而辐射式设计,就像上面打印机的例子,如果改变了纸张IPaper的接口,那么纸张的实现类 A4Paper() 和 B5Paper()就都要修改。也就是说对于抽象类,如果需要添加新的方法,可以直接在抽象类中添加具体的实现,子类可以不进行变更;而对于接口则不行,如果接口进行了变更,则所有实现这个接口的类都必须进行相应的改动。

  • 相关阅读:
    VS2008 环境中完美搭建 Qt 4.7.4 静态编译的调试与发布 Inchroy's Blog 博客频道 CSDN.NET
    编写可丢弃的代码
    c++ using namespace std; 海明威 博客园
    解决MySQL server has gone away
    nginx upstream 调度策略
    (2006, 'MySQL server has gone away') 错误解决 dba007的空间 51CTO技术博客
    Linux IO模型漫谈(2) 轩脉刃 博客园
    redis源码笔记 initServer 刘浩de技术博客 博客园
    MySQLdb批量插入数据
    词库的扩充百度百科的抓取你知道这些热词吗? rabbit9898 ITeye技术网站
  • 原文地址:https://www.cnblogs.com/superfly123/p/10475041.html
Copyright © 2020-2023  润新知