接口 interface

java的接口是通过interface来实现

为什么要有接口?

java没有多继承 可以用接口来实现多继承的功能
因为类是两个相同事物的共性抽取出来的,接口可以 看做是两个不同事物的某一个特性抽取出来.

      eg: 小东和牧羊犬都会吃饭,难道他们俩是同一类事物吗? 肯定不是的.那么他们都会吃饭的这个特性就可以抽取成一个接口来使用

接口说白了也即是 完成类所不合理的一些特征而存在的 弥补类的短板 

 

 

接口的概述;

 一方面,有时必须从几个类中派生出一个子类,继承它们所有的属性和方 法。但是,Java不支持多重继承。有了接口,就可以得到多重继承的效果。
另一方面,有时必须从几个类中抽取出一些共同的行为特征,而它们之间又 没有is-a的关系,仅仅是具有相同的行为特征而已。
    例如:鼠标、键盘、打 印机、扫描仪、摄像头、充电器、MP3机、手机、数码相机、移动硬盘等都 支持USB连接。
接口就是规范,定义的是一组规则,体现了现实世界中“如果你是/要...则 必须能...”的思想。继承是一个"是不是"的关系,而接口实现则是 "能不能" 的关系。
 接口的本质是契约,标准,规范,就像我们的法律一样。制定好后大家都 要遵守。

 

接口和类的区别:

 

 

 

 

 

接口的特征


接口的方法不能有方法体

* * 1:接口的使用 * interface 来定义 * * 2: java中 接口和类是并列的两个结构 * * 3 : 定义接口中的成员 * jdk7 以及以前 : 接口中只能定义全局常量和抽象方法 * > 全局常量: public static final :但是书写是常常省略 public static fianl * > 抽象方法: public abstract * * jdk8: 除了定义全局常量和抽象方法之外,还可以定义静态方法, 默认方法 * * * 4 : 接口中不能定义构造器,也就是不能被实例化 * * 5: 在java开发中几口通过让类去实现(implements)的方式来使用, * 如果实现类 覆盖了接口中的所有抽象方法,则此实现类就可以实例化 * 如果实现类没有重写完所有的抽象方法,则此实现类还是一个抽象类 * * * * 6: java类实现多个接口 -----> 弥补了java单继承性的局限性 * 格式 : class AA implements BB, CC, DD, EE * * * 7: 接口与接口之间可以继承,而且可以多继承 * * 8: 接口的具体使用: 体现了多态 * * 9: 接口实际上可以看做是一种规范


定义Java类的语法格式:先写extends,后写implements
   class SubClass extends SuperClass implements InterfaceA{ } 
一个类可以实现多个接口,接口也可以继承其它接口

因为接口内的方法是默认以public abstract开头的 所以默认是抽象的如果这个接口内的方法没有被子类全部重写完毕子类就是一个抽象类
实现接口的类中必须提供接口中所有方法的具体实现内容,方可实 例化。否则,仍为抽象类

接口之间可以多继承 接口之间的继承使用extends来继承

 

 

 

面试题:

排错

interface A { int x = 0;
}
class B {
    int x = 1;
}
class C extends B implements A {
    public void pX() {
System.out.println(x); }
    public static void main(String[] args) {
        new C().pX();
} }

 

pX() 方法的x没有声明形参,所以此处有问题

 

interface Playable {
    void play();
}
interface Bounceable {
    void play();
}
interface Rollable extends Playable, Bounceable {
     Ball ball = new Ball("PingPang");
}


class Ball implements Rollable {
    private String name;
    public String getName() {
        return name;
}
    public Ball(String name) {
        this.name = name;
}
public void play() {
ball = new Ball("Football"); System.out.println(ball.getName());
} }
Rollable接口中没有重写  继承来的接口中的方法, 
Ball 中的ball属性是不能重写定义的  因为此变量是在Rollable 接口中定义的  ,
接口中的变量时常量是不可以被改变的

 

 

 

练习题

定义一个接口用来实现两个对象的比较。 interface CompareObject{

        public int compareTo(Object o); //若返回值是 0 , 代表相等; 若为正数,代表当前对象大;负数代表当前对象小
}
定义一个Circle类,声明redius属性,提供getter和setter方法 定义一个ComparableCircle类,继承Circle类并且实现CompareObject接口。在 ComparableCircle类中给出接口中方法compareTo的实现体,用来比较两个圆的半 径大小。 定义一个测试类InterfaceTest,创建两个ComparableCircle对象,调用compareTo 方法比较两个类的半径大小。 思考:参照上述做法定义矩形类Rectangle和ComparableRectangle类,在 ComparableRectangle类中给出compareTo方法的实现,比较两个矩形的面积大小

 

import java.util.Date;

public class XiTest {
    public static void main(String[] args) {
        ComparableCir c1 = new ComparableCir(3.4);
        ComparableCir c2 = new ComparableCir(3.6);
        int compareValue = c1.compareTo(c2);
        if(compareValue >0){
            System.out.println("c1比c2大");
        }else if (compareValue < 0){
            System.out.println("c2对象大");
        }else{
            System.out.println("一样大");
        }
    }
}




interface CompareTest{
    public int compareTo(Object o);
}

class Cir{
    double redius;
    public Cir(double redius){
        this.redius = redius;
    }

    public double getRedius() {
        return redius;
    }

    public void setRedius(double redius) {
        this.redius = redius;
    }
}

class ComparableCir extends  Cir implements CompareTest{
    public ComparableCir(double redius){
        super(redius);
    }

    @Override
    public  int compareTo(Object o){
        if(this.getRedius() == 0){
            return  0;
        }
        if(o instanceof ComparableCir){
            ComparableCir comparableCir = (ComparableCir) o;
            if(this.getRedius() > comparableCir.getRedius()){
                return 1;
            }else if(this.getRedius() < comparableCir.getRedius()){
                return -1;
            }else{
                return 0;
            }
        }else{
            return 0;
        }
    }
}
实现

 

 

 

接口的代理模式:

/**
 * 接口的应用: 代理模式
 */


// 虽然是通过代理类对象去掉方法但是 实际把被代理类对象传递进去 包含了 被代理类对象
public class NetWorkTest {
    public static void main(String[] args) {
        ServerTest serverTest = new ServerTest();
        ProxyServerTest proxyServerTest = new ProxyServerTest(serverTest);
        proxyServerTest.browse();  // 联网实现的一些检查工作  ,   真实的服务器访问网络

    }
}


interface NetWork{
    public void browse();
}

// 被代理类
class ServerTest implements NetWork{

    @Override
    public  void  browse(){
        System.out.println("真实的服务器访问网络");
    }
}


// 代理类
class ProxyServerTest implements NetWork{
    private NetWork work;
    public ProxyServerTest(NetWork work){
        this.work = work;
    }

    public void check(){
        System.out.println("联网实现的一些检查工作");
    }

    public  void browse(){
        check();
        work.browse();
    }
}
代理模式

 

 

 

java8中接口的特性

 

 

java8中可以书写:
静态方法带方法体,
默认方法


* java8中接口除了定义全局常量和静态方法中 * * > 接口中定义的静态方法只能接口去调用 * > 如果子类(或者实现类)继承的父类和实现的接口中有同名同参数的方法,那么子类在没有重写此方法的情况下调用的是父类中同名同参数的方法---->类优先原则

如果实现类实现了多个接口,而多个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的时候就会报错,---->接口冲突
* 那么我们就必须在实现类中重写此方法

 

eg:

public class J8 {
    public static void main(String[] args) {
        CompareA compareA = new CompareA();
        // compareA.method1() 报错 java8中接口中的静态方法只能接口自己调用  其他的实现类不可以去调用
        //通过实现类的对象可以调用默认方法, 如果重写后接口中的方法 那么调用的是实现类内的重写方法
        Java8.method1();
        compareA.method2();
        compareA.method3();  // 继承的父类也有  实现的接口中也有此方法那么调用的是父类中的方法


        TestB testB = new TestB();
//        testB.method1();  静态方法只可以自己调用不可以实现类去调用
    }
}


/**
 * java8中接口除了定义全局常量和静态方法中
 *
 *      > 接口中定义的静态方法只能接口去调用
 *      > 如果子类(或者实现类)继承的父类和实现的接口中有同名同参数的方法,那么子类在没有重写此方法的情况下调用的是父类中同名同参数的方法---->类优先原则
 */
interface  Java8{
    // 静态方法
    public static  void method1(){
        System.out.println("java8的新特性接口中的方法是可以有方法体的");
    }

    // 默认方法
    public default void method2(){
        System.out.println("java8接口新特性");
    }
    //默认方法
    default void method3(){
        System.out.println("java8接口新特性");
    }
}


class CompareA extends  SuperClass implements Java8 {

}


class SuperClass {
    public void method3(){
        System.out.println("我是父类中的method3");
    }
}

 

 

在调用是接口中的静态方法只能接口本身自己去调用,如下 实现类只可以调用默认方法

 

 

 

 

如果实现类实现了多个接口,而多个接口中定义了同名同参数的默认方法,那么在实现类没有重写此方法的时候就会报错,---->接口冲突
* 那么我们就必须在实现类中重写此方法

 

因为上面定义了 TestB接口定义了method3()方法 而实现类实现了TestB和TestA接口  又没有重写method3方法就会报错

 

 

 

 

 

在实现类中调用接口中的被重写的方法

接口.super.方法()

eg:

class TestB extends  TestD implements TestA, TestC{
    public void method3(){ //重写的时候权限必须大于上一级
        System.out.println("TestB 重写方法");
TestA.
super.method3(); //调用接口中的默认方法 }

 

 

总结:

若一个接口中定义了一个默认方法,而另外一个接口中也定义了一个同名同 参数的方法(不管此方法是否是默认方法),在实现类同时实现了这两个接 口时,会出现:接口冲突。
 解决办法:实现类必须覆盖接口中同名同参数的方法,来解决冲突。
 若一个接口中定义了一个默认方法,而父类中也定义了一个同名同参数的非 抽象方法,则不会出现冲突问题。因为此时遵守:类优先原则。接口中具有 相同名称和参数的默认方法会被忽略。

 

解决接口冲突

interface Filial{  //孝顺的
    default void help(){
        System.out.println("老妈我来救你");
    }
}

interface Spoony{ //痴情的
    default void help(){
        System.out.println("媳妇别怕 我来了");
    }
}


class father{
     public void help(){
         System.out.println("先救你妈妈");
    }
}

class man extends father implements Filial, Spoony {
    @Override
    public void help(){
        System.out.println("我该怎么办");
        super.help();
        Filial.super.help();
        Spoony.super.help();
    }
}

 

Summarize

接口内部的元素定义:
   

        定义的变量必须初始化赋值 因为你定义的的变量时fianl的常量 变量在没有赋值的时候是为空的 不是有值的

        方法的定义:  
                   默认的是方法都是  public  abstract  开头 如果是抽象方法 不能有方法体;  如果接口中定义的有抽象方法 子类必须要全部重写完接口的抽象方法否则子类也是一个抽象类

                    java8后支持  public  staticpublic default  静态方法和默认方法的定义 是静态方法和默认方法是可以有方法体的 

接口的继承

    接口可以被类继承 也可以被接口继承
    类继承接口使用implements 接口继承接口使用extends来继承 接口继承接口可以多继承中间以逗号隔开
     class implements interface

interface extends interface1, interface2

如果子类继承的两个接口中都同时定义了一个同名同参数的方法那么这个子类必须要重写这个方法不然就会冲突报错

 

接口的好处:

1、利于代码的规范

这样做的目的一方面是为了给开发人员一个清晰的指示,告诉他们哪些业务需要实现;同时也能防止由于开发人员随意命名而导致的命名不清晰和代码混乱,影响开发效率。

2、有利于对代码进行维护

可以一开始定义一个接口,把功能菜单放在接口里,然后定义类时实现这个接口,以后要换的话只不过是引用另一个类而已,这样就达到维护、拓展的方便性。

3、保证代码的安全和严密

一个好的程序一定符合高内聚低耦合的特征,能够让系统的功能较好地实现,而不涉及任何具体的实现细节。这样就比较安全、严密一些,这一思想一般在软件开发中较为常见。

 

 

 

.

 

posted @ 2019-10-18 11:05  可爱的红领巾  阅读(402)  评论(0编辑  收藏  举报