[JAVA · 初级]:13.接口

定义

什么是?

它是一套标准,是一套规则,是一套对所有类的统一的要求。

做什么?

它是为了实现多继承而出现的。

有什么?

它只包含两种成份:

1) 公共的静态的常量。

2) 抽象方法。

如何做?

通过 interface 关键字来实现 。

格式:

<span style="font-size:18px;"><span style="font-size:18px;">public interface 接口名 { ..... }</span></span>

已知的:

1) 现存的接口(由专家提供)。

2) 自定义的接口(由程序员自己编写)。

<span style="font-size:18px;"><span style="font-size:18px;"> int obj1.compareTo(obj2 )</span></span>

规定: 对象比较大小必须使用 compareTo 作为方法名, 比较大小后的结果必须是一个int型整数。

且当这个整数大于零时,则表示前者大于后者;

当这个整数小于零时,则表示前者小于后者;

当这个整数等于零时,则表示前者与后者相等。

然而,这两个对象按什么属性比较,当前无法确定。因此,这个方法就必须是抽象的。

因此,这个方法如下:

<span style="font-size:18px;"><span style="font-size:18px;"> public abstract intcompareTo( Object obj );</span></span>

此方法为抽象的。根据所学知识可知:抽象方法要么在抽象类中,要么在接口中。

试想: 当以上 compareTo()方法置于抽象类中时,则问: 所有类是否均可以与这个抽象类发生继承关系?

答案: 否定的。

当以上 compareTo()方法置于接口中,则问: 所有类是否可以与这个接口发生继承(实现)关系?

答案: 肯定的。

由于对象比较大小的规则可以提前制定,因此,专家就为程序员提前准备了一个接口 java.lang.Comparable,其中

存放了 以上抽象方法[ int compareTo(Object obj )  ]

如何实现接口?

通过关键字   implements 关键字来实现

格式为:

<span style="font-size:18px;"><span style="font-size:18px;"> public class 类  implements  接口1 { ...... }</span></span>

格式为:

<span style="font-size:18px;"><span style="font-size:18px;">public class 类  implements  接口1, 接口2, ... { ...... }</span></span>

注意: 在Java中,一个类可以不实现接口,也可只实现一个接口, 还可以实现多个接口.

注意: 当一个类实现了接口时,则这个类必须重写来自接口的所有抽象方法。否则,这个类就是抽象类。

应用

编写一个类去实现给定的接口。同时,在这个类中重写来自接口的所有抽象方法。

最后,由此类去创建对象,调用对象的方法来解决业务。完成。

1) 导入 import 包.接口名; 如: import java.lang.Comparable;

2) 编写类去实现这个接口;  如: public class Student implementsComparable { ...... };

3) 在这个类中重写来自接口的抽象方法;  如:  重写 compareTo()方法;

4) 应用(编写应用程序)。

<span style="font-size:18px;"><span style="font-size:18px;">Demo
//学生类
packagecom.hqg.oop.d39;

//1导入 接口
importjava.lang.Comparable; 

importcom.hqg.oop.d38.a2.MyDate;

public classStudent extends Object  implementsComparable { //2 实现接口

       //3 重写来自接口的所有抽象方法: 目的是让当前类的对象拥有比较大小的能力。
       @Override
       public int compareTo(Object obj) {
              Student st2 = (Student)obj;

              if( this.score > st2.score ){
                     return 1;
              }else if( this.score <st2.score ){
                     return -1;
              }else{                   return 0;
              }

              //return -(this.score - st2.score);
              /**
               *         1)基本类型的数据比较相等用 == , 比较大小 用关系运算符
               *         2)引用类型的数据比较相等用 equals() 方法,  比较大小用  compareTo()方法。
               *
               */
              //return  this.name.compareTo(st2.name);

              //return-(this.SEX+"").compareTo( st2.SEX+"" );

              int x = (this.SEX+"").compareTo(st2.SEX+"" );
              int y = -(this.score - st2.score);
              if( x == 0 ){
              return y;
              }else{
                     return x;
              }

              String s1 =this.getBirthday().toString();
              String s2 =st2.getBirthday().toString();
              return s1.compareTo( s2 );

       }

       //实例变量
       private String name;
       private final boolean SEX;
       private MyDate birthday;

       private int score;

       //构造器
       public Student() {
              int n = (int)(2 * Math.random());
              this.SEX = n == 1;
       }
       public Student(String name, MyDatebirthday, int score) {
              this();
              this.name = name;
              this.birthday = birthday;
              this.score = score;
       }
       public Student(String name, boolean sEX,MyDate birthday, int score) {
              this.name = name;
              SEX = sEX;
              this.birthday = birthday;
              this.score = score;
       }
       public String getName() {
              return name;
       }
       public void setName(String name) {
              this.name = name;
       }
       public MyDate getBirthday() {
              return birthday;
       }
       public void setBirthday(MyDate birthday){
              this.birthday = birthday;
       }
       public int getScore() {
              return score;
       }
       public void setScore(int score) {
              this.score = score;
       }
       public boolean isSEX() {
              return SEX;
       }

       @Override
       public String toString() {
              return " " + name +"     " + (SEX ? "男":"女") + "    " + birthday + "  "+ score;
       }
}
package com.hqg.oop.d39;

//importjava.util.Arrays;  //专家给定的工具类, 用来实现 数组的排序
importcom.hqg.oop.d38.a2.MyDate;

public classQuTest5 {
       public static void main(String[] args) {
              Student[] ss = new Student[5];

              ss[0] = new Student("张无忌", new MyDate(1992, 10, 11), 650);
              ss[1] = new Student("赵敏", false, new MyDate(1992, 5, 15),680);
              ss[2] = new Student("韦一笑", new MyDate(1993, 1, 31), 670);
              ss[3] = new Student(“蛛儿”, true, new MyDate(1992, 9, 10), 660);
              ss[4] = new Student("周芷若", false, new MyDate(1993, 2, 7),700);

              System.out.println("五个学生的初始状态如下:");
              System.out.println("============================");
              System.out.println("姓名       性别  出生日期     入学成绩");
              System.out.println("============================");
              for(Student tem : ss){
                     System.out.println( tem );
                     System.out.println("----------------------------");
              }

              //业务1 :所有学生按入学成绩升序排列
              Arrays.sort( ss );

              System.out.println("\n\n五个学生按入学成绩升序如下:");
              System.out.println("============================");
              System.out.println("姓名       性别  出生日期     入学成绩");
              System.out.println("============================");
              for(Student tem : ss){
                     System.out.println( tem );
                     System.out.println("----------------------------");
              }

              //业务2: 入学成绩降序排列
              //将 compareTo()方法中的值取反即可降序
              //业务3: 按姓名排序
              //将 compareTo()方法中的返回值改变姓名比较后的值。
              //业务4: 性别分类 
                     //布尔类型不能比较大小,就将其转换为其它类型数据再比较。
              //业务5:
                     //复合条件排序
              //业务6: 按出生日期排序
       }
}     

class Arrays {
       public static void sort( Student[] stu ){
              for(int i = 0; i <stu.length-1;  i++){
                     for(int j = 0; j <stu.length - i - 1;  j++ ){
                            int re =stu[j].compareTo( stu[j+1] ); //两个学生比较大小,结果存放在re中

                            if( re > 0 ){
                                   //交换
                                   Student tem =stu[j];
                                   stu[j] =stu[j+1];
                                   stu[j+1] =tem;
                            }
                     }
              }
       }
}</span></span>

较抽象类

所谓抽象类是用来表征我们在对问题领域进行分析、设计中得出的抽象概念,是对一系列看上去不同,但是本质上相同的具体概念的抽象;所谓接口,相当于电源插座,可插入构件相当于电器。可插入构件的关键在于存在一个公用的接口,以及每个构件都实现了这个接口。接口是实现构件的可插入性的关键。

(1)从语法层来讲,Java语言对于抽象类和接口给出了不同的定义方式,下面以定义一个名为Demo的抽象类为例来说明这种不同。

Demo抽象类的定义方式如下:

<span style="font-size:18px;"><span style="font-size:18px;">abstract classDemo {

abstract voidmethod1();

abstract void method2();

…

}</span></span>

Demo的接口定义方式如下:

<span style="font-size:18px;"><span style="font-size:18px;">interface Demo {

void method1();

void method2();

…
}</span></span>

在抽象类的定义中,Demo可以有自己的数据成员,也可以有非abstract的成员方法,而在接口的定义中,Demo只能够有static final数据成员,所有的成员方法都是abstract的。从某种意义上说,接口是一种特殊形式的抽象类。

从编程的角度来看,首先,抽象类和接口的继承规则不同,抽象只允许单继承,而一个类却可以实现多个接口。接口对于多重继承的支持方面的一种折中考虑;其次,在抽象类的定义中,可以赋予方法的默认行为,而在接口的定义中,方法不能拥有默认行为,必须使用委托,从某种意义上来说,接口比抽象类更为抽象化。

(2)从设计层来讲,抽象类在Java语言中体现了一种继承关系,要想使得继承关系合理,父类和派生类之间必须存在"Is-A"关系,即父类和子类在概念本质上应该是相同的。对于接口来说则不然,接口并不要求实现者和接口定义在概念本质上是一致的,仅仅是实现了接口定义的契约而已。考虑这样一个例子,假设在有一个关于Door的抽象概念,该Door具有执行两个动作open和close,此时我们可以通过抽象类或者接口来定义一个表示该抽象概念的类型,定义方式分别如下所示:

Door抽象类的定义方式如下:

<span style="font-size:18px;"><span style="font-size:18px;">abstract classDoor {

abstract voidopen();

abstract voidclose();

}</span></span>

Door的接口定义方式如下:

<span style="font-size:18px;"><span style="font-size:18px;">interface Door {

void open();

void close();

}</span></span>

其他具体的Door类型可以extends使用抽象类方式定义的Door或者implements使用接口方式定义的Door。看起来好像使用抽象类和接口没有大的区别。如果现在要求Door还要具有报警的功能。下面将罗列出可能的解决方案,并从设计层对方案进行分析。

解决方案一:

简单的在Door的定义中增加一个alarm方法,如下:

<span style="font-size:18px;"><span style="font-size:18px;">abstract classDoor {

abstract voidopen();

abstract voidclose();

abstract voidalarm();

}</span></span>

或者

<span style="font-size:18px;"><span style="font-size:18px;">interface Door {

void open();

void close();

void alarm();

}</span></span>

那么具有报警功能的AlarmDoor的定义方式如下:

<span style="font-size:18px;"><span style="font-size:18px;">class AlarmDoorextends Door {

void open(){…}

void close(){…}

void alarm(){…}

}</span></span>

或者

<span style="font-size:18px;"><span style="font-size:18px;">class AlarmDoorimplements Door{

void open(){…}

void close(){…}

void alarm(){…}

}</span></span>

这种方法违反了接口隔离原则,在Door的定义中把Door概念本身固有的行为方法和另外一个概念“报警器”的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为“报警器”这个概念的改变(比如:修改alarm方法的参数)而改变,反之依然。

解决方案二:

既然open、close和alarm属于两个不同的概念,根据接口隔离原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有:这两个概念都使用抽象类方式定义;两个概念都使用接口方式定义;一个概念使用抽象类方式定义,另一个概念使用接口方式定义。

显然,由于Java语言不支持多重继承,所以两个概念都使用抽象类方式定义是不可行的。后面两种方式都是可行的,但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。

如果两个概念都使用接口方式来定义,那么就反映出两个问题:第一,我们可能没有理解清楚问题领域,AlarmDoor在概念本质上 到底是Door还是报警器?第二,如果我们对于问题领域的理解没有问题,比如:我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的,那么我们在实现时就没有能够正确的揭示我们的设计意图,因为在这两个概念的定义上(均使用接口方式定义)反映不出上述含义。

如果我们对于问题领域的理解是:AlarmDoor在概念本质上是Door,同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢?前面已经说过,抽象类在Java语言中表示一种继承关系,而继承关系在本质上是"Is-A"关系。所以对于Door这个概念,我们应该使用抽象类方式来定义。另外,AlarmDoor又具有报警功能,说明它又能够完成报警概念中定义的行为,所以报警概念可以通过接口方式定义。如下所示:

<span style="font-size:18px;"><span style="font-size:18px;">abstract classDoor{

abstract voidopen();

abstract voidclose();

}

interface Alarm{

void alarm();

}

class AlarmDoorextends Door implements Alarm{

void open(){…}

void close(){…}

void alarm(){…}

}</span></span>

这种实现方式基本上能够明确的反映出我们对于问题领域的理解,正确的揭示我们的设计意图。其实抽象类表示的是"Is-A"关系,interface表示的是"Has-A"关系,在选择时可以作为一个依据,当然这是建立在对问题领域的理解上的,比如:如果我们认为AlarmDoor在概念本质上是报警器,同时又具有 Door的功能,那么上述的定义方式就要反过来了。

抽象类和接口是Java语言中的两种定义抽象类的方式,它们之间有很大的相似性。但是对于它们的选择却又往往反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理,因为它们表现了概念间的不同的关系。只有正确理解面向对象的设计原则并灵活使用抽象类和接口,才能设计出易用的系统。

业务思想

接口的出现大大的方便了我们变编程人员的工作,多继承现象也可以顺利解决。其实,接口孕育于生活,稍一体会,就感觉到生活中接口的重要性呢,于编程亦如此。

时间: 2024-08-29 22:40:19

[JAVA · 初级]:13.接口的相关文章

老白的JAVA课程13 接口

之前我们讲到了java4大特征的最后一个抽象的特征,其实在抽象这个特征里面,我们还有一个特征-接口,今天我们就来学一学接口.  用电脑,手机等电子产品来比喻接口,可以更好的理解,比如用符合接口的插头就可以了.  接口具有很好的扩展性,方便.  接口的由来   例子:奥拓奥迪都是汽车,汽车的维护都是可以用调节引擎和更换汽油的方法,那么奥拓和奥迪也都可以:但是有了更多的维护对象以后,比如说大货车,卡车等等,其他的对象不一定需要每一步维护,或者都不需要维护:又比如不同枪支有不同特性的例子.  因此,我

JavaSE入门学习21:Java面向对象之接口(interface)(二)

一接口实现的多态 在上一篇博文:JavaSE入门学习20:Java面向对象之接口(interface)(一)中提到了接口的实现存在多态性,那么 这一篇主要就要分析接口实现的多态. 实例一 Test.java源文件代码: public class Test{ public static void main(String[] args){ //实现接口Singer Singer s1 = new Student("Amy"); s1.sing(); s1.sleep(); s1.study

java的List接口的实现类 ArrayList,LinkedList,Vector 的区别

Java的List接口有3个实现类,分别是ArrayList.LinkedList.Vector,他们用于存放多个元素,维护元素的次序,而且允许元素重复. 3个具体实现类的区别如下: 1. ArrayList是最常用的List实现类,内部是通过数组实现的,它允许对元素进行快速随机访问.数组的缺点是每个元素之间不能有间隔,当数组大小不满足时需要增加存储能力,就要将已经有数组的数据复制到新的存储空间中.当从ArrayList的中间位置插入或者删除元素时,需要对数组进行复制.移动.代价比较高.因此,它

java----数据结构与算法----JavaAPI:java.util.Collection接口

Java API--java.util.Collection接口 /** * @author chen * @date 20170317 * @description:本程序讲述Collection接口 * java.util.Collection * 概述:Collection接口是Set和List接口的父接口,Collection接口中定义了一些 * 用于集合元素操作的方法,被其子接口以及子接口的实现类所继承 * 构造函数 * java中接口不能有构造函数 * 成员函数: * [1]概述,由

java类与接口练习

java类与接口练习--coursera java 课程作业 1.注意代码应该使用题目中所要求的语法要素:2.注意良好的代码风格:3.注意提交整个project,上传压缩后的附件,互评时可被成功执行:4.注意写一个简要的代码说明(请说明使用的IDE等): 编写一个小的程序,其中定义一些接口.类.抽象类,定义它们的成员(字段及方法), 要求使用setter/getter, static, final, abstract,@Override等语法要素,并写一个main函数来使用它们.这些类.接口可以

Java基础十--接口

Java基础十--接口 一.接口的定义和实例 1 /* 2 abstract class AbsDemo 3 { 4 abstract void show1(); 5 abstract void show2(); 6 } 7 8 当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用 9 另一种形式定义和表示,就是 接口 interface. 10 */ 11 12 //定义接口使用的关键字不是class,是interface. 13 //interface编译后还是.class文件,其实本质

Java容器Map接口

Map接口容器存放的是key-value对,由于Map是按key索引的,因此 key 是不可重复的,但 value 允许重复. 下面简单介绍一下Map接口的实现,包括HashMap,LinkedHashMap,WeakHashMap,Hashtable,IdentityHashMap和TreeMap.需要注意的是,Map接口并没有继承Collection接口! 1.HashMap HashMap 继承于AbstractMap,实现了Cloneable.java.io.Serializable接口

Java面向对象程序设计--接口和内部类

1.接口的定义: In the Java programming language, an interface is not a class but a set of requirements for classes that want to conform the interface. 说明: 1) Interface 不是class,虽然interface具有class的一些特点,例如能够继承,能够定义相同类型的变量,而且和C++的abstract class非常像,但Java 的inter

java中的接口深层理解

深入理解Java的接口和抽象类 对于面向对象编程来说,抽象是它的一大特征之一.在Java中,可以通过两种形式来体现OOP的抽象:接口和抽象类.这两者有太多相似的地方,又有太多不同的地方.很多人在初学的时候会以为它们可以随意互换使用,但是实际则不然.今天我们就一起来学习一下Java中的接口和抽象类.下面是本文的目录大纲: 一.抽象类 二.接口 三.抽象类和接口的区别 若有不正之处,请多多谅解并欢迎批评指正,不甚感激. 请尊重作者劳动成果,转载请标明原文链接: http://www.cnblogs.

java----数据结构与算法----JavaAPI:java.util.List接口

java.util.List接口 /** * @author lxrm * @date 20170307 * @description 本程序讲述java.util.List接口的用法 * java.util.List * 概述: * 1)List接口是Collection接口的子接口,所以List接口拥有Collection接口所定义的所有成员函数 * 除了有其父接口Collection中所定义的所有函数之外,List接口也添加了自己的函数,使得List集合拥有自己的特色 * List接口中新