• 1. Java 接口 2008-09-19
  • 2. 1.1 接口接口 与抽象类一样都是定义多个类的共同属性,它声明了若干抽象方法和常量 使抽象的概念更深入了一层,是一个“纯”抽象类,它只提供一种形式,并不提供实现 允许创建者规定方法的基本形式:方法名、参数列表以及返回类型,但不规定方法主体 也可以包含基本数据类型的数据成员,但它们都默认为static和final
  • 3. 1.1.1 接口的作用及语法接口的作用 是面向对象的一个重要机制 实现多继承,同时免除C++中的多继承那样的复杂性 接口是用来规范类的,它可以避免类在设计上的不一致 这在多人合作的开发中犹为重要 ,比如一个人,把他封装一个类对象,作为一个接口实现的话,一继承就能实现人的所有的属性和方法,并且重复多次的利用,就不用每次都自己写了,而某个人的某个行为与大多数人不同的话,就可以重写这个方法,要是普通类的话只能调用的不能重写,这就是接口的好处 。接口
  • 4. 接口允许我们在看起来不相干的对象之间定义共同行为1.1.1 接口的作用及语法 ——与抽象类的不同接口
  • 5. 保险公司的例子 具有车辆保险、人员保险、公司保险等多种保险业务,在对外提供服务方面具有相似性,如都需要计算保险费(premium)等,因此可声明一个Insurable 接口 在UML图中,实现接口用带有空三角形的虚线表示1.1.1 接口的作用及语法 ——例1_1<> InsurableCompanyPersonCar接口
  • 6. 接口的语法 声明格式为 [接口修饰符] interface 接口名称 [extends 父接口名]{ …//方法的原型声明或静态常量 } 接口的数据成员一定要赋初值,且此值将不能再更改,允许省略final关键字 接口中的方法必须是“抽象方法”,不能有方法体,允许省略public及abstract关键字1.1.1 接口的作用及语法接口
  • 7. 例1.1中的Insurable 接口声明如下,可见其中的方法都是抽象方法 public interface Insurable { public int getNumber(); public int getCoverageAmount(); public double calculatePremium(); public Date getExpiryDate(); }1.1.1 接口的作用及语法 ——例1_1保险接口的声明接口
  • 8. 声明一个接口Shape2D,可利用它来实现二维的几何形状类Circle和Rectangle 把计算面积的方法声明在接口里 pi值是常量,把它声明在接口的数据成员里 interface Shape2D{    //声明Shape2D接口 final double pi=3.14;   //数据成员一定要初始化 public abstract double area(); //抽象方法 } 在接口的声明中,允许省略一些关键字,也可声明如下 interface Shape2D{ double pi=3.14; double area(); }1.1.1 接口的作用及语法 ——例1_2接口8
  • 9. 1.1.2 实现接口接口的实现 接口的实现,使用implements关键字 语法如下 public class 类名称 implements 接口名称 { /* Bodies for the interface methods */ /* Own data and methods. */ } 必须实现接口中的所有抽象方法 来自接口的方法必须声明成public接口
  • 10. 实现接口Insurable,声明汽车类实现例1.1中的Insurable接口,实现接口中的所有抽象方法 public class Car implements Insurable { public int getPolicyNumber() { // write code here } public double calculatePremium() { // write code here } public Date getExpiryDate() { // write code here } public int getCoverageAmount() { // write code here } public int getMileage() { //新添加的方法 //write code here } }1.1.2 实现接口 ——例1_3接口
  • 11. 对象可以被转型为其所属类实现的接口类型 getPolicyNumber、calculatePremium是Insurable接口中声明的方法 getMileage是Car类新添加的方法,Insurable接口中没有声明此方法 Car  jetta = new Car(); Insurable  item = (Insurable)jetta; //对象转型为接口类型 item.getPolicyNumber(); item.calculatePremium(); item.getMileage();        // 接口中没有声明此方法,不可以 jetta.getMileage();       // 类中有此方法,可以 ((Car)item).getMileage(); // 转型回原类,可调用此方法了 1.1.2 实现接口 ——对象转型接口
  • 12. 1.1.2 实现接口 ——例1_4class Circle implements Shape2D { double radius; public Circle(double r) { radius=r; } public double area() { return (pi * radius * radius); } }class Rectangle implements Shape2D { int width,height; public Rectangle(int w,int h) { width=w; height=h; } public double area() { return (width * height); } } 声明Circle与Rectangle两个类实现Shape2D接口 接口
  • 13. 测试类 public class InterfaceTester { public static void main(String args[]){ Rectangle rect=new Rectangle(5,6); System.out.println("Area of rect = " + rect.area()); Circle cir=new Circle(2.0); System.out.println("Area of cir = " + cir.area()); } } 运行结果 Area of rect = 30.0 Area of cir = 12.561.1.2 实现接口 ——例1_4运行结果接口
  • 14. 声明接口类型的变量,并用它来访问对象 public class VariableTester { public static void main(String []args) { Shape2D var1,var2; var1=new Rectangle(5,6); System.out.println("Area of var1 = " + var1.area()); var2=new Circle(2.0); System.out.println("Area of var2 = " + var2.area()); } } 输出结果 Area of var1 = 30.0 Area of var2 = 12.56 1.1.2 实现接口 ——例1_1接口
  • 15. MovableObject接口定义了所有“可移动对象”能做的事情 public interface  MovableObject { public boolean    start(); public void       stop(); public boolean    turn(int degrees); public double     fuelRemaining(); public void       changeSpeed(double kmPerHour); }1.1.2 实现接口 ——MovableObject接口接口
  • 16. Plane、Car、 Train、 Boat 分别实现 MovableObject 接口 public class Plane implements  MovableObject { public int   seatCapacity; public Date  lastRepairDate; //实现MovalbelObject接口的所有方法 public boolean start() { //启动飞机,成功则返回true } public void stop() { //停止 } public boolean turn(int degrees) { //转向,成功则返回true} public double fuelRemaining() { //返回燃料剩余量 } public void changeSpeed(double kmPerHour) { //改变速度 } //plane类自己的方法: public Date getLastRepairDate() { //... } public double calculateWindResistance() { //....} }1.1.2 实现接口 ——MovableObject接口的实现接口
  • 17. 为 MovableObjects安装遥控器(remote control) public class RemoteControl {   private MovableObject   machine;     RemoteControl(MovableObject m) {machine = m; }   //按下“启动”按钮: public void start() {     boolean okay = machine.start();     if (!okay) display("No Response on start");     //... } } remote control 构造方法的形参类型为 MovableObject,它可以是Plane, Car, Train, Boat, 等等1.1.2 实现接口 ——RemoteControl类接口
  • 18. 1.1.3 多重继承多重继承 Java的设计以简单实用为导向,不允许一个类有多个父类 但允许一个类可以实现多个接口,通过这种机制可实现多重继承 一个类实现多个接口的语法如下 [类修饰符] class 类名称 implements 接口1,接口2, … { … … } 接口
  • 19. Car类可以实现接口Insurable,Drivable,Sellable public class Car implements Insurable, Drivable, Sellable {    .... }1.1.3 多重继承 ——Car的例子接口
  • 20. 声明Circle类实现接口Shape2D和Color Shape2D具有pi与area()方法,用来计算面积 Color则具有setColor方法,可用来赋值颜色 通过实现这两个接口,Circle类得以同时拥有这两个接口的成员,达到了多重继承的目的 interface Shape2D{ //声明Shape2D接口 final double pi=3.14; //数据成员一定要初始化 public abstract double area(); //抽象方法 } interface Color{ void setColor(String str); //抽象方法 } 1.1.3 多重继承 ——例1_6接口
  • 21. class Circle implements Shape2D,Color // 实现Circle类 { double radius; String color; public Circle(double r) //构造方法 { radius=r; } public double area() //定义area()的处理方式 { return (pi*radius*radius); } public void setColor(String str) //定义setColor()的处理方式 { color=str; System.out.println("color="+color); } }接口1.1.3 多重继承 ——例1_6
  • 22. 测试类 public class MultiInterfaceTester{ public static void main(String args[]) { Circle cir; cir=new Circle(2.0); cir.setColor("blue"); System.out.println("Area = " + cir.area()); } } 输出结果 color=blue Area = 12.16接口1.1.3 多重继承 ——例1_6运行结果
  • 23. 1.1.4 接口的扩展接口的扩展 接口可通过扩展的技术派生出新的接口 原来的接口称为基本接口(base interface)或父接口(super interface) 派生出的接口称为派生接口(derived interface)或子接口(sub interface) 派生接口不仅可以保有父接口的成员,同时也可加入新成员以满足实际问题的需要 实现接口的类也必须实现此接口的父接口 接口扩展的语法 interface 子接口的名称 extends 父接口的名称1,父接口的名称2,… { … … } 接口
  • 24. Shape是父接口,Shape2D与Shape3D是其子接口。Circle类及Rectangle类实现接口Shape2D,而Box类及Sphere类实现接口Shape3D 1.1.4 接口的扩展 ——例1_7Shape接口Shape2D接口Shape3D接口Sphere类Box类Rectangle类Circle类接口ShapeShape2D接口Shape3D接口
  • 25. 部分代码如下 // 声明Shape接口 interface Shape{ double pi=3.14; void setColor(String str); } //声明Shape2D接口扩展了Shape接口 interface Shape2D extends Shape { double area(); }1.1.4 接口的扩展 ——例1_7接口
  • 26. class Circle implements Shape2D { double radius; String color; public Circle(double r) { radius=r; } public double area() { return (pi*radius*radius); } public void setColor(String str){ color=str; System.out.println("color="+color); } } public class ExtendsInterfaceTester{ //测试类 public static void main(String []args) { Circle cir; cir=new Circle(2.0); cir.setColor("blue"); System.out.println("Area = " + cir.area()); } } 1.1.4 接口的扩展 ——例1_7接口
  • 27. 运行结果 color=blue Area = 12.56 说明 首先声明了父接口Shape,然后声明其子接口Shape2D 之后声明类Circle实现Shape2D子接口,因而在此类内必须明确定义setColor()与area()方法的处理方式 最后在主类中我们声明了Circle类型的变量cir并创建新的对象,最后通过cir对象调用setColor()与area()方法 1.1.4 接口的扩展 ——例1_7运行结果接口
  • 28. FixedInsurable 和DepreciatingInsurable接口 都继承了Insurable接口 实现它们类也必须实现Insurable接口中的所有方法 public interface DepreciatingInsurable extends  Insurable {     public double computeFairMarketValue(); } public interface FixedInsurable extends  Insurable {     public int getEvaluationPeriod();// }1.1.4 接口的扩展 ——Insurable接口的例子接口
  • 29. 1.1.5 接口-与抽象类之区别区别一,两者表达的概念不一样。抽象类是一类事物的高度聚合,那么对于继承抽象类的子类来说,对于抽象类来说,属于“是”的关系;而接口是定义行为规范,因此对于实现接口的子类来说,相对于接口来说,是“行为需要按照接口来完成”。这些听起来有些虚,举个例子。例如,狗是对于所有狗类动物的统称,京哈是狗,牧羊犬是狗,那么狗的一般特性,都会在京哈,牧羊犬中找到,那么狗相对于京哈和牧羊犬来说,就属于这类事物的抽象类型;而对于“叫”这个动作来说,狗可以叫,鸟也可以叫。很明显,前者相当于所说的是抽象类,而后者指的就是接口。
  • 30. 1.1.5 接口-与抽象类之区别区别二,抽象类在定义类型方法的时候,可以给出方法的实现部分,也可以不给出;而对于接口来说,其中所定义的方法都不能给出实现部分。 例如: public abstract class AbsTest { public virtual void Test() { Debug.WriteLine( "Test" ); } public abstract void NewTest(); } public interface ITest { void Test(); void NewTest(); }
  • 31. 1.1.5 接口-与抽象类之区别区别三,继承类对于两者所涉及方法的实现是不同的。继承类对于抽象类所定义的抽象方法,可以不用重写,也就是说,可以延用抽象类的方法;而对于接口类所定义的方法或者属性来说,在继承类中必须要给出相应的方法和属性实现。 区别四,在抽象类中,新增一个方法的话,继承类中可以不用作任何处理;而对于接口来说,则需要修改继承类,提供新定义的方法。
  • 32. 1.1.6 接口的好处知道了两者的区别,再来说说,接口相对于抽象类的优势。 好处一,java的类型继承只能是单继承的,也就是说一个类型只能继承一个类型,而可以继承多个接口。 好处二,由于接口只是定义属性和方法,而与真正实现的类型没有太大的关系,因此接口可以被多个类型重用。相对于此,抽象类与继承类的关系更紧密些。
  • 33. 1.1.6 接口的好处  好处三,通过接口,可以减少类型暴露的属性和方法,从而便于保护类型对象。当一个实现接口的类型,可能包含其他方法或者属性,但是方法返回的时候,可以返回接口对象,这样调用端,只能通过接口提供的方法或者属性,访问对象的相关元素,这样可以有效保护对象的其他元素。
  • 34. 1.1.7 综述其实在继承中,到底使用接口还是抽象类也不一定。接口是固定的,约定俗成的,因此在继承类中必须提供接口相应的方法和属性的实现。而对于抽象类来说,抽象类的定义方法的实现,贯穿整个继承树,因此其中方法的实现或者重写都是不确定的。因此相对而言,抽象类比接口更灵活一些。 如下给出两者的简单对比表格。#
  • 35. 1.1.7 综述接口抽象类多继承支持不支持变量类型Final static无限制方法实现继承类型中必须给出方法实现继承类可以不给出
  • 36. 1.1.7 综述总的来说,abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制,正是由于这两种机制的存在,才赋予了Java强大的面向对象能力,而且两者有些相辅相成的关系。因此我并不强调用什么而不用什么,那么问题的关键在于,如何把这两种手段合理的应用到程序当中,这才是至关重要.
  • 37. 1.1.8 接口-应用示例(设计模式)工厂模式分为:简单工厂模式、工厂模式、抽象工厂模式。 简单工厂模式又称“静态工厂方法模式”,属于创建性模式。 简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。
  • 38. 接口-应用示例(Simple Factory)
  • 39. 接口-应用示例(Simple Factory)范例(农场公司)
  • 40. 接口-应用示例(Factory)工厂模式又称为“多态性工厂”,属于设计模式中的创建性模式。 工厂模式采用一个抽象工厂的角色,负责所有产品的创建工作。 负责具体创建各种产品的工厂类是抽象工厂的子类。
  • 41. 接口-应用示例(Factory)工厂方法模式和简单工厂模式在定义上的不同是很明显的。工厂方法模式的核心是一个抽象工厂类,而不像简单工厂模式, 把核心放在一个实类上。工厂方法模式可以允许很多实的工厂类从抽象工厂类继承下来, 从而可以在实际上成为多个简单工厂模式的综合,从而推广了简单工厂模式。 反过来讲,简单工厂模式是由工厂方法模式退化而来。设想如果我们非常确定一个系统只需要一个实的工厂类, 那么就不妨把抽象工厂类合并到实的工厂类中去。而这样一来,我们就退化到简单工厂模式了。
  • 42. 接口-应用示例(Factory)
  • 43. 接口-应用示例(Abstract Factory)
  • 44. 接口-应用示例(Abstract Factory)范例(窗体风格)