《Java编程思想》之接口(Java中实现多重继承!)

1、interface不仅仅只是一个极度抽象的类,因为它允许人们通过创建一个能够被向上转型为多种基类型的类,来实现某种类似C++多重继承变种的特性。

2、像类一样,可以在interface关键字前面添加public关键字(但仅限于该接口在与其同名的文件中被定义),或者不添加它而使其只是具有包访问权限,这样它就只能在同一个包内可用。

3、可以选择在接口中显示地将方法声明为public的,但即使你不这么做,它们也是public的。因此当实现一个接口时,在接口中被定义的方法必须被定义为public

4、Java中,在方法的继承过程中,其可访问权限不能被降低。

5、接口也可以包含字段,但是它们隐式为static和final的。

6、因为接口是根本没有任何具体实现的——也就是说,没有任何与接口相关的存储;因此,也就无法阻止多个接口的组合,也就是“多重继承”。如下例子:

  1. interface CanFight{  
  2.    void fight();  
  3. }  
  4. interface CanSwim{  
  5.    void swim();  
  6. }  
  7. interface CanFly{  
  8.    void fly();  
  9. }  
  10. class ActionCharacter{  
  11.    public void fight(){  
  12.       System.out.println("ActionCharacter.fight()");  
  13.    }  
  14. }  
  15. class Hero extends ActionCharacter implements CanFight, CanSwim, CanFly{  
  16.    public void swim(){  
  17.       System.out.println("Hero.swim()");  
  18.    }  
  19.    public void fly(){  
  20.       System.out.println("Hero.fly()");  
  21.    }  
  22.    /**1.注意CanFight中的fight()方法并没在这里定义 
  23.     * 2.这是因为CanFight接口与ActionCharacter类中的fight()方法的特征签名是一样的。 
  24.     * 3.所以即使Hero没有显式地提供fight()的定义,其定义也因ActionCharacter而随之而来。 
  25.     * 4.若把ActionCharacter的fight()改为private,就会出现提示说 
  26.     *   “类型 Hero必须实现继承的抽象方法 CanFight.fight()”的错误。 
  27.     * 5.若把ActionCharacter的fight()改为private,就会出现提示说 
  28.     *   “继承的方法 ActionCharacter.fight()不能隐藏 CanFight中的公用抽象方法”的错误。 
  29.     */  
  30.     
  31. }  
  32. public class Adventure{  
  33.    public static void t(CanFight x){x.fight();}  
  34.    public static void u(CanSwim x){x.swim();}  
  35.    public static void v(CanFly x){x.fly();}  
  36.    public static void w(ActionCharacter x){x.fight();}  
  37.    public static void main(String[] args){  
  38.       Hero h = new Hero();  
  39.       t(h);  
  40.       u(h);  
  41.       v(h);  
  42.       w(h);  
  43.    }  
  44. }  

运行结果:


1).注意CanFight中的fight()方法并没有在Hero定义

2).这是因为CanFight接口与ActionCharacter类中的fight()方法的特征签名是一样的。

3).所以即使Hero没有显式地提供fight()的定义,其定义也因ActionCharacter而随之而来。

4).若把ActionCharacter的fight()改为private,就会出现提示说“类型 Hero必须实现继承的抽象方法CanFight.fight()”的错误。

5).若把ActionCharacter的fight()改为private,就会出现提示说“继承的方法 ActionCharacter.fight()不能隐藏CanFight中的公用抽象方法”的错误。


7、以上例子所展示的就是使用接口的核心原因:为了能够向上转型为多个基类型

8、使用接口的第二原因:与使用抽象基类相同,防止客户端程序员创建该类的对象,并确保这仅仅是建立一个接口。

9、应该使用接口还是抽象类:当要创建不带任何方法定义和成员变量的基类时,使用接口。

10、事实上,如果知道某事物应该成为一个基类,那么第一选择应该是使它成为一个接口,只有在强制你必须具有方法定义和成员变量时,才应该选择抽象类,或者在必要时使其成为一个具体类。

11、接口通过继承来扩展,如下:

  1. interface Plant{  
  2.    void grow();  
  3. }  
  4. interface Flower extends Plant{  
  5.    void bloom();  
  6. }  
  7. interface Apple extends  Plant, Flower{  
  8.    void fruit();  
  9. }  
  10. class RedApple implements Apple{  
  11.    public void grow(){  
  12.       System.out.println("RedApple isgrowing.");  
  13.    }  
  14.    public void bloom(){  
  15.       System.out.println("RedApple isblooming.");  
  16.    }  
  17.    public void fruit() {  
  18.       System.out.println("RedApple isfruiting.");  
  19.    }  
  20. }  

心细的人可能看到了Apple接口后extends  Plant, Flower。一般情况下,只可以将extends用于单一类,但是既然接口可以由多个其它接口产生,那么在创建一个新接口时,extends当然可以引用多个基类接口此语法仅适用与接口的继承。

12、Java中构建如同C++的enum类型那样具备类型安全(变量的取值被限定在一个有限的范围内):

  1. public final class Month{  
  2.    private String name;  
  3.    //private构造器,无法创建它的任何实例,所有实例都是在类的内部有其身创建的finalstatic实例  
  4.    private Month(String name){  
  5.       this.name = name;  
  6.    }  
  7.    public String toString(){  
  8.       return name;  
  9.    }  
  10.    public static final Month  
  11.       JAN = new Month("January"),  
  12.       FEB   = new Month("February"),  
  13.       MAR   = new Month("March"),  
  14.       APR   = new Month("April"),  
  15.       MAY   = new Month("May"),  
  16.       JUN   = new Month("June"),  
  17.       JUL   = new Month("July"),  
  18.       AUG   = new Month("August"),  
  19.       SEP   = new Month("September"),  
  20.       OCT   = new Month("October"),  
  21.       NOV   = new Month("November"),  
  22.       DEC   = new Month("December");  
  23.    public static final Month[] month = {  
  24.       JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC  
  25.    };  
  26.    public static final Month number(int order){  
  27.       return month[order - 1];  
  28.    }  
  29.    public static void main(String[] args){  
  30.       //curMonth是一个Month对象,它仅可以被赋予一个Month对象。这就体现了类型安全性。  
  31.       Month curMonth = Month.JAN;  
  32.       System.out.println(curMonth);  
  33.       curMonth = Month.number(12);  
  34.       System.out.println(curMonth);  
  35.       //这种方式同样也允许你可互换地使用==或equal(),因为Month的每一个值都仅有一个实例。  
  36.       System.out.println(curMonth == Month.DEC);  
  37.       System.out.println(curMonth.equals(Month.DEC));  
  38.       System.out.println(Month.month[3]);  
  39.    }  
  40. }  

运行结果:


13、接口可以嵌套在类或其他接口中。嵌套接口可以拥有public和“包访问”两种可视性。同时,public和包访问的嵌套接口都可以被实现为public、包访问以及private的嵌套类。

  1. class A{  
  2.    interface B{  
  3.       void fromB();  
  4.    }  
  5.    interface D{  
  6.       void fromD();  
  7.    }  
  8.    //嵌套接口可以是private访问权限。  
  9.    //它带来的好处是:强制接口中的方法定义不要添加任何类型信息(也就是说,不允许向上转型),不明白,请看看最后的解说。  
  10.    private interface I{  
  11.       void fromI();  
  12.    }  
  13.    //private的嵌套接口可以被实现为private  
  14.    private class J implements I{  
  15.       public void fromI() {  
  16.         System.out.println("E.J.fromI()");  
  17.       }  
  18.    }  
  19.    //private的嵌套接口也可以被实现为public  
  20.    public class J1 implements I{  
  21.       public void fromI() {  
  22.         System.out.println("E.J1.fromI()");  
  23.       }  
  24.    }  
  25.    //结合getI()和setI()方法实现“向上转型”?!  
  26.    public I getI(){  
  27.       return new J1();  
  28.    }  
  29.    public void setI(I i){  
  30.       i.fromI();  
  31.    }  
  32.    //接口之间可以嵌套,嵌套在另一个接口中的接口只能是public的  
  33.    interface K{  
  34.       interface L{//此处也默认是public的  
  35.         void fromL();  
  36.       }  
  37.    }  
  38. }  
  39. public class E implements A.D{  
  40.    public void fromD() {  
  41.       System.out.println("E.fromD()");  
  42.    }  
  43.    //内部类F public  
  44.    public class F implements A.B{  
  45.       public void fromB() {  
  46.         System.out.println("E.F.fromB()");  
  47.       }  
  48.    }  
  49.    //内部类G protected  
  50.    protected class G implements A.B{  
  51.       public void fromB() {  
  52.         System.out.println("E.G.fromB()");  
  53.       }  
  54.    }  
  55.    //内部类I private  
  56.    private class H implements A.B{  
  57.       public void fromB() {  
  58.         System.out.println("E.I.fromB()");  
  59.       }  
  60.    }  
  61.    public static void main(String[] args){  
  62.       E e = new E();  
  63.       e.fromD();  
  64.       //内部的实例化  
  65.       E.F f = e.new F();  
  66.       f.fromB();  
  67.        
  68.       E.G g = e.new G();  
  69.       g.fromB();  
  70.        
  71.       E.H h = e.new H();  
  72.       h.fromB();  
  73.       //"实现了private接口I"的"public类J1"的实例化。  
  74.       A.J1 j1 = new A().new J1();  
  75.       j1.fromI();  
  76.        
  77.       A a = new A();  
  78.       //A.I i = a.getI();//类型 A.I 不可视  
  79.       //A.J1 j = a.getI();//不能从 A.I转换为 A.J1  
  80.       //a.getI().fromI();//类型 A.I 不可视  
  81.       a.setI(a.getI());  
  82.    }  
  83. }  
运行结果:


getI(),返回private接口的引用的public方法。在main()中,数次使用返回值的行为都失败了。只有一种方式可以成功,那就是将返回值交给有权使用它的对象。在上例中,是一个A的对象a同过setI()方法来实现的。


以上内容整理自《Java编程思想》,如有遗漏,请您不吝指出!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值