接口与实现
接口
概述:Java 不支持多重继承(子类只能有一个父类)。
为了克服Java单继承的缺点,Java使用了接口,一个类实现了多个接口。
使用关键字interface来定义一个接口。接口的定义和类很相似,分为接口的声明和接口体。
接口的变量和方法的构造规则:
实现接口
接口例题
public interface Computable {
int MAX=46;
int f(int x);
}
public class China implements Computable { //China类实现Computable接口
int number;
public int f(int x) {
int sum=0;
for(int i=1;i<=x;i++){
sum=sum+i;
}
return sum;
}
}
public class Japan implements Computable{
int number;
public int f(int x) {
return MAX+x; //直接使用接口中的常量
}
}
public class exma {
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+",zhang求和结果"+henlu.f(100));
}
}
接口的UML图
表示接口的UML图和表示的UML图类似,使用一个长方形描述一个接口的主要构成,将长方形垂直的分为三层。
顶部第一层是名字层,接口的名字必须是斜体字形,而且需要用《interface》修饰名字,并且该修饰和名字分列在两行。
第二层是常量层,列出接口中的常量及类型,格式是“常量名字:类型”。
第3层是方法层,也称操作层,列出接口中的方法及返回类型,格式是“方法名字(参数列表):类型”。
接口回调
接口回调是指:可以把实现某一接口的类创建的对象的引用赋给该接口声明的接口变量中,那么该类接口变量就可以调用被类重写的接口方法。实际上,当接口变量调用被类重写的接口方法时,就是通知相应的对象调用这个方法。
如下例
interface showMess{
void 显示商标(String s);
}
class TV implements showMess{
public void 显示商标(String s) {
System.out.println(s);
}
}
class PC implements showMess{
public void 显示商标(String s) {
System.out.println(s);
}
}
public class exam {
public static void main(String[] args) {
showMess sm; //声明接口变量
sm=new TV(); //接口变量中存放对象的引用
sm.显示商标("长城牌电视机"); //接口回调
sm=new PC();
sm.显示商标("联想奔月5008PC机");
}
}
理解接口
(1)接口可以抽象出重要的行为标准,该行为的标准用抽象方法来表示。
(2)可以把实现接口的类的对象的引用赋值给接口变量,该接口变量可以调用被该类实现的接口方法,即体现该类根据接口里的行为标准给出的具体行为。
接口的思想在于它可以要求某些类有相同名称的方法,但方法的具体内容(方法体的内容)可以不同,即要求这些类实现接口,以保证这些类一定有接口中所声明的方法(即所谓的方法绑定)。接口在要求一些类有相同名称的方法的同时,并不强迫这些类具有相同的父类。
接口与多态
可以通过在接口中声明若干个abstract方法,表明这些方法的重要性,方法体的内容细节由实现接口的类去完成。使用接口进行程序设计的核心思想是使用接口回调,即接口变量存放实现该接口的类的对象的引用,从而接口变量就可以回调类实现的接口方法。
如下例
interface CompurerAverage{
public double average(double a,double b);
}
class A implements CompurerAverage{
public double average(double a,double b) {
double aver=0;
aver=(a+b)/2;
return aver;
}
}
class B implements CompurerAverage{
public double average(double a,double b){
double aver=0;
aver=Math.sqrt(a*b);
return aver;
}
}
public class lianxi {
public static void main(String[] args) {
CompurerAverage computer;
double a =11.23,b=22.78;
computer =new A();
double result=computer.average(a, b);
System.out.printf("%5.2f和%5.2的算术平均值:%5.2f\n",a,b,result);
computer =new B();
result=computer.average(a, b);
System.out.printf("%5.2f和%5.2的几何平均值:%5.2f",a,b,result);
}
}
接口参数
如果一个方法的参数是接口类型,我们就可以将任何实现该接口的类的实例的引用传递给该接口参数,那么接口参数就可以回调类实现的接口方法。
例如
interface SpeakHello{
void speakHello();
}
class Chinese implements SpeakHello{
public void speakHello(){
System.out.println("中国人习惯问候语:你好,吃饭了吗?");
}
}
class English implements SpeakHello{
public void speakHello(){
System.out.println("英国人习惯问候语:你好,天气不错");
}
}
class KindHello{
public static KindHello kindHello;
public static void lookHllo(SpeakHello hello) { //接口类型参数
hello.speakHello(); //接口回调
}
}
public class lianxi {
public static void main(String[] args) {
KindHello.kindHello=new KindHello();
KindHello.lookHllo(new Chinese());
KindHello.lookHllo(new English());
}
}
abstract类与接口的比较
接口和abstract类的比较如下:
1、abstract类和接口都可以有abstract方法。
2、接口中只可以有常量,不能有变量;而abstract类中即可以有常量也可以有变量。
3、abstract类中也可以有非abstract方法,接口不可以。
面向接口编程
面向接口去设计程序,可以通过在接口中声明若干个abstract方法,表明这些方法的重要性,方法体的内容细节由实现接口的类去完成。
使用接口进行程序设计的核心思想是使用接口回调,即接口变量存放实现该接口的类的对象的引用,从而接口变量就可以回调类实现的接口方法。
总结
实例
设计一个动物声音“模拟器”,希望模拟器可以模拟许多动物的叫声,要求如下:
编写接口Animal
Animal接口有两个抽象方法cry()和getAnimalName(),即要求各种具体的动物给出自己的叫声和种类名称。
编写模拟器类Simulator
该类有一个playSound(Animal animal)方法,该方法的参数是Animal类型。即animal可以调用Animal的接口类重写的cry()方法播放具体动物的声音,调用子类重写的getAnimalName()方法显示动物种类的名称。
编写Animal接口的子类:Dog和Cat类
编写主类Application(用户程序)
在主类Application的main方法中至少包含如下代码;
Simulatoer simulator =new Simulator();
simulator.playSound(new Dog());
simulator.playSound(new Cat());
下表为Simulator、Animal、Dog、Cat的UML图。
//Animal.java
public interface Animal{
public abstract void cry();
public abstract String getAnimalName();
}
//Simulator.java
public class Simulator{
public void playSound(Animal animal){
System.out.print("现在播放"+animal.getAnimalName()+"类的声音:");
animal.cry();
}
}
//Dog.java
public class Dog implements Animal{
public void cry(){
System.out.println("汪汪...汪汪");
}
public String getAnimalName(){
return "狗";
}
}
//Cat.java
public class Cat implements Animal{
public void cry(){
System.out.println("喵喵...喵喵");
}
public String getAnimalName(){
return "猫";
}
}
//Application.java
public class Application{
public static void main(String args[]){
Simulator simulator = new Simulator();
simulator.playSound(new Dog());
simulator.playSound(new Cat());
}
}
上一篇: 组装SDK之arm交叉编译器的制作
下一篇: 嵌入式开发之Opencv(一)交叉编译