接口与实现

接口的定义和类的定义很相似,可以分为接口声明和接口体积,和类不同的是,使用关键字interface来声明自己是一个接口。 
格式如下; 
interface 接口的名字 
这里需要注意的是: 
1、如果一个非抽象类实现了某个接口,那么这个类必须重写这个接口中的所有方法。 
2、如果一个类声明实现一个接口,但是没有重写接口中的从所有方法,那么这个类必须是抽象类,也就是说抽象类既可以重写接口中的方法,也可以直接拥有接口中的方法。 
3、程序可以用接口名访问接口中的常量,但是如果一个类实现了接口,那么该类可以直接在类体中使用该接口的常量。 
4、在我们定义接口的时候,如果关键字interface 前面加一个public关键字,就成这样的接口是一个public接口,public接口可以被任何一个类实现。如果一个接口不加public修饰。就称作是友好接口,友好接口可以被 与该接口在同一个包中的类实现。 
5、如果父类实现了某个接口,那么子类自然也就实现了该接口,子类不必再显式地使用关键字implement声明实现这个接口。 

 

6、接口也可以被继承,即可以通过关键字extends声明一个接口是另外一个接口的子接口。由于接口中的方法和常量都是public的,子接口将继承父接口中的全部方法和常量。 

 

 

举个例子吧: 
在这个例子中China类和Japan类分别继承computable接口。 
下面是具体的源代码: 
China类

package Example14;

import Example5.ComputerAver;

public class China implements Computable {
    int number;
    public int f(int x) {
        //public关键字别漏了
        int sum = 0;
        for(int i=1; i<= x;i++){
            sum+=i;
        }
        return sum;
    }
//重写方法f 
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Japan类

package Example14;

public class Japan implements Computable {
    int number;
    @Override
    public int f(int x) {
        return MAX + x;
        //直接调用接口中的常量
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

computable接口

package Example14;

public interface Computable {
    int MAX = 46;
    public abstract int f(int x);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

主函数:

package Example14;

public class Demo {

    public static void main(String[] args) {
        China zhang;
        Japan henlu;
        zhang = new China();
        henlu = new Japan();
        zhang.number = 32 + Computable.MAX;
        henlu.number = 14 + Computable.MAX;
        System.out.println("zhang的学号" + zhang.number + "  zhang求和结果" + zhang.f(100));
        System.out.println("henlu的学号" + henlu.number + "  henlu求和结果" + henlu.f(100));
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

运行结果:

zhang的学号78  zhang求和结果5050
henlu的学号60  henlu求和结果146
  • 1
  • 2

例子2: 
动机类MotorVehicles :

package Example15;

//动机类
public abstract class MotorVehicles {
    abstract void brake();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

收费的接口MoneyFare :

package Example15;

interface MoneyFare {
    void charge();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

空调接口ControlTemperature:

package Example15;

interface ControlTemperature {
    void controlAirTemperature();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Bus类继承了动机类并且实现了收费接口

package Example15;
//bus实现MoneyFare
//一个接口

public class Bus extends MotorVehicles implements MoneyFare{

    void brake(){
        System.out.println("公共汽车使用毂式刹车");
    }//重写

    public void charge() {
        System.out.println("公共汽车:一元/张,不计算公里数");
    }


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

Taxi类继承了动机类并且实现了空调和收费接口

package Example15;

public class Taxi extends MotorVehicles implements MoneyFare ,ControlTemperature {


    public void charge() {
        System.out.println("出租车:2元/公里,起价3公里");
    }


    void brake() {
        System.out.println("出租车使用盘式刹车技术:");
    }


    public void controlAirTemperature() {
        System.out.println("出租车安装了Hair空调");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

Cinrma 实现了空调和收费接口

package Example15;

public class Cinrma implements MoneyFare, ControlTemperature {

    @Override
    public void controlAirTemperature() {
        System.out.println("电影院安装了中央空调");
    }

    @Override
    public void charge() {
        System.out.println("电影院:门票,10/张");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

主函数调用

package Example15;

public class Demo {

    public static void main(String[] args) {
        Bus bus = new Bus();
        Taxi taxi = new Taxi();
        Cinrma cinrma = new Cinrma();
        bus.brake();
        bus.charge();
        taxi.charge();
        taxi.brake();
        taxi.controlAirTemperature();
        cinrma.charge();
        cinrma.controlAirTemperature();
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

调试结果:

公共汽车使用毂式刹车
公共汽车:一元/张,不计算公里数
出租车:2元/公里,起价3公里
出租车使用盘式刹车技术:
出租车安装了Hair空调
电影院:门票,10/张
电影院安装了中央空调
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

关于接口回调 
和类一样,接口也是Java中一种重要的数据类型,用接口声明的变量称作接口变量。 
接口属于引用型变量,接口变量中可以存放实现该接口类的实例应引用,即存放对象的引用。 
“接口回调”这个词是借用了C语言中的指针回调的术语,表示一个变量的地址在某一个时刻放在一个指针变量中,那么指针变量就可以间接操作该变量中存放的数据。 
在Java语言中,接口回调是指:可以把实现某一接口的类创建的对象的引用赋值给该接口声明的接口变量,那么该接口变量就可以调用被类实现的接口方法。事实上,当接口变量调用被类实现的接口方法时,就是通知相应的对象调用这个方法。 
举个例子:假设Com是一个接口,ImpleCom类是实现Com接口的类

Com com;
ImpleCom impleCom;
com = impleCom;// 这样是合法的。将impleCom 的对象的引用赋值给com接口。
  • 1
  • 2
  • 3

类似上转型对象调用子类重写的方法 
下面我们举个例子: 
ShowMessage 接口:

package Example16;

public interface ShowMessage {
    void 显示商标(String s);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

PC类实现了ShowMessage接口

package Example16;

public class PC implements ShowMessage {

    public void 显示商标(String s) {
        System.out.println(s);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

TV类实现了ShowMessage 接口:

package Example16;

public class TV implements ShowMessage {

    public void 显示商标(String s) {
        System.out.println(s);
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

主函数:

package Example16;

public class Demo {

    public static void main(String[] args) {
        ShowMessage message;
        message = new TV();
        message.显示商标("长虹牌电视机");
        message = new PC();
        message.显示商标("华硕A550jk4200");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

调试结果

长虹牌电视机
华硕A550jk4200
  • 1
  • 2
  • 3

关于接口和多态: 
接口产生的多态就是指不同的类在实现同一个接口时可能具有不同的实现方法,那么接口变量在回调接口方法是就可能具有多种形态。 
下面我们举个例子: 
接口ComputerAverage :

package Example17;

interface ComputerAverage {
    public double average(double a,double b);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

类A实现接口ComputerAverage

package Example17;

public class A implements ComputerAverage {

    public double average(double a, double b) {
        double aver = 0;
        aver = (a+b)/2;
        return aver;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

类B实现接口ComputerAverage

package Example17;

public class B implements ComputerAverage {

    public double average(double a, double b) {
        double aver = 0;
        aver = Math.sqrt(a*b);
        return aver;
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

主函数调用:

package Example17;

public class Demo {

    public static void main(String[] args) {
        ComputerAverage average;
        double a = 11.45,b = 45.45;
        average = new A();
        double result = average.average(a, b);
        System.out.println(a + "和" + b + "的算术平均值:" + result );
        average = new B();
        result = average.average(a, b);
        System.out.println(a + "和" + b + "的几个平均值:" + result );
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

调试结果:

11.45和45.45的算术平均值:28.450000000000003
11.45和45.45的几个平均值:22.81233219116362
  • 1
  • 2
  • 3

在这个例子中类A和类B都实现了ComputerAverage接口,但是实现的方式不同。 
关于接口参数: 
如果一个方法参数的类型是接口类型,我们就可以将任何实现该接口的类的实例的引用传递给接口参数,那么接口参数就可以回调类实现的接口方法,下面举个例子: 
基本接口SpeakHello.java

package Example18;

interface SpeakHello {
    void speakHello();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

Chinese类实现接口:

package Example18;

public class Chinese implements SpeakHello {

    public void speakHello() {
        System.out.println("中国人习惯问候语:你好!吃饭了吗?");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

English类实现接口

package Example18;

public class English implements SpeakHello {

    public void speakHello() {
        System.out.println("英国人习惯性用语:你好,天气不错!");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

KindHello类使用接口类型参数,实现接口回调

package Example18;

public class KindHello {
    public  void lookHello(SpeakHello hello) {
        //接口类型参数,接口回调
        hello.speakHello();

    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

主调用函数:

package Example18;

public class Demo {

    public static void main(String[] args) {
        KindHello kindHello = new KindHello();
        kindHello.lookHello(new Chinese());
        kindHello.lookHello(new English());
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

调试结果:

中国人习惯问候语:你好!吃饭了吗?
英国人习惯性用语:你好,天气不错!
  • 1
  • 2
  • 3

abstract类与接口的比较: 
1、abstract类和接口都可以有abstract方法。 
2、接口中只可以有常量,不能有变量;而abstract类中既可以有常量也可以有变量。 
3、abstract类中也可以有非abstract方法,而接口必须是抽象方法。 
需要注意的是: 
在设计程序时应当根据具体的方法来确定是使用抽象类还是接口。abstract类除了提供重要的需要子类重写的abstract方法之外,也提供了子类可以继承的变量和非abstract方法。如果某个问题需要使用继承才能更好地解决,比如:子类除了需要重写父类的abstract方法,还需要从父类继承一些变量或者继承一些重要的非abstract方法,就可以考虑使用abstract类。如果某个问题不需要继承,只是需要若干个子类给出某些重要的abstract方法的实现细节,就可以考虑使用接口。

一个面向接口编程的应用举例:

问题的提出: 
设计一个广告牌,希望所设计的广告牌可以展示许多公司的广告词。 
1、问题的分析: 
如果我们设计的创建广告牌的类中是某个具体公司类。(例如联想公司类),声明了对象。那么我们的广告牌就缺少弹性,因为用户一旦需要广告牌展示其他公司的广告词,就需要修改广告牌类的代码,比如用长虹公司声明成员变量。 
如果没当用户有了新的需求,就会导致修改类的某部分代码,那么就应当将这部分代码从该类重分割出去,使它和其他稳定的代码之间是松耦合的关系(否则系统缺乏弹性,难以维护),即将每种可能的变化对应地交给实现接口的类(抽象类的子类)去负责完成。 
2、设计接口。 
根据以上的对问题的分析,首先设计一个接口Advertisement,改接口有2个方法show-Advertisement()和getCorpName();那么实现Advertisement接口的类必须重写,show-Advertisement()和getCropName()方法,及要求各个公司给出具体的广告词和公司的名称。 
3、设计广告牌类 
然后我们设计AdvertisementBoard类(广告牌),该类有一个show(Advertisement adver)方法,该方法的参数adver是Advertisement接口类型(就像人们常说的,广告牌对外留有接口)。显然,该及参数adver可以存放任何实现Advertisement接口的类的对象的引用,并且回调重写的接口方法ShowAdvertisement()来显示公司的广告词,回调类重写的接口方法getCropName()来显示公司的名称。 
下面是具体实现的代码: 
广告Advertisement接口:

package Example19;
/**
 * 接口
 * @author 10497
 *
 */
public interface Advertisement {
    public void ShowAdvertisement();
    public String getCropName();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

广告牌类,完成接口回调:

 package Example19;
/**
 * 广告牌类
 * @author 10497
 *
 */

public class AdvertisementBoard {
    public void Show(Advertisement adver){//使用接口参数
        System.out.println(adver.getCropName() + "的广告词如下:");
        adver.ShowAdvertisement();
        //接口回调
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

安踏公司实现接口:

package Example19;

public class AnTaCrop implements Advertisement {

    public void ShowAdvertisement() {
        System.out.println("@@@@@@@@@@@@@@@@@@@");
        System.out.println("安踏,运动永不止步~~");
        System.out.println("@@@@@@@@@@@@@@@@@@@");
    }

    public String getCropName() {
        return "安踏有限公司";
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

特步公司实现接口

package Example19;

public class TeBuCorp implements Advertisement {

    public void ShowAdvertisement() {
        System.out.println("**********************");
        System.out.println("特步,非一般的感觉~~~~~");
        System.out.println("**********************");
    }

    public String getCropName() {
        return "特步有限公司";
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

主调用函数:

package Example19;

public class Application {
    public static void main(String args[]){
        AdvertisementBoard board = new AdvertisementBoard();
        board.Show(new AnTaCrop());
        board.Show(new TeBuCorp());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

调试结果:

安踏有限公司的广告词如下:
@@@@@@@@@@@@@@@@@@@
安踏,运动永不止步~~
@@@@@@@@@@@@@@@@@@@
特步有限公司的广告词如下:
**********************
特步,非一般的感觉~~~~~
**********************

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值