zoukankan      html  css  js  c++  java
  • java 接口学习

    你应该知道接口是一种契约,它与实现方式无关

    但是类,即使是抽象类,你都能自定义成员变量,而成员变量往往就与实现方式有关。

    这一点的实际意义不大。

    但是有一点,类会暴露太多不必要,甚至不能暴露的东西,你看一下java.util中,大部分的数据结构,都被设计成了接口-抽象类-最后实际类

    例如Collection-List
    L-AbstractCollection
    L-AbstractList
    L-ArrayList

    但是有一个,由于历史原因,被设计成了类,比如Stack extends Vector,
    你应该知道Stack的数据访问模式,就只能是LIFO,但是Vector是一个List,可以随机访问,可以任意增减。

    结果Stack s = new Stack();

    不光能够pop/push/peer还能add,get,set,remove

    如果你用一个接口IStack 里面只有pop/push/peer方法,然后仍然通过继承Vector的方式实现,

    IStack s = new MyStack();

    此时,就无法add,get,set,remove

    举个生动一点的例子

    public interface BritishSpy {
    public String speak(); //英国间谍讲英语
    }
    
    public interface GermanSpy {
    public String sprechen(); //德国间谍讲德语
    }
    
    public class DoubleAgent implements BritishSpy, GermanSpy {
    public String speak() { return "Hello"; }
    public String sprechen() { return "Gutentag"; }
    }
    // hovertree.com
    public class Agency {
    public static void toMI5(BritishSpy spy) {
    //军情5处当然只能说英语,做英国间谍
    spy.speak();
    //spy.sprechen();不可见
    }
    
    public static void inGermany(GermanSpy spy) {
    //spy.speak();不可见
    spy.sprechen();
    }
    
    public static void main(String[] args) {
    DoubleAgent da = new DoubleAgent();
    BritishSpy es = (BritishSpy) da;
    GermanSpy gs = (GermanSpy) da;
    toMI5(da); //MI5也不知道他是一个双重间谍,只知道他是BritishSpy
    toMI5(es); //更安全  何问起
    //toMI5(gs); 不可能
    inGermany(da); //在德国还是安全的,德国人不知道他的双重间谍身份,只知道他是GermanSpy
    inGermany(gs); 
    //inGermany(es); 不可能
    }
    }

    假设你只用class,因为不能多重继承,所以,speak()/sprechen()比然声明在同一个class里面


    public abstract class DoubleAgent extends Spy/**(略...)*/ {
    public abstract String speak();
    public abstract String sprechen();
    }

    public class PoorDoubleAgent {
    public String speak() { return "Hello"; }
    public String sprechen() { return "Gutentag"; }
    }

    晚了,不管你PoorDoubleAgent a = new PoorDoubleAgent();还是DoubleAgent a = new PoorDoubleAgent();,全世界都知道他是一个双重间谍,他到哪里都必死无疑
    前面举了一个关于“安全性”方面的例子

    接口只暴露给对方(比如Agent的军情5处方法)它所需要的足够信息,其他无关的,甚至有害的信息不会暴露给对方。因为,我传给你的是接口类型,我除了是这个接口(和这个接口的父接口,inteface A extends B, C)的实例外,你顶多知道我是一个Object(不是int:P),其他的姓甚名谁,哪里住址,父母安好,兄妹几何都与你无关,我们只需要关心我们签订的合同(接口) 

    再举一个有关灵活性方面的例子

    假设某公司已经有一个更新过N代的,逻辑复杂无比
    public class A extends B /** where b extends c, c extends d and so on... */ {
    public void init() {...}
    public void release() {...}
    public String doXXX() {...}
    public String doYYY() {...}
    }

    而这个A又被很多类继承或使用,doXXX/doYYY 方法已经无法更改

    假设现在这个公司要参加某个标准化组织,而这个组织要求所有提供这样的方法

    String getXXX(); String getYYY();

    加入用接口标准化组织只要规定成员们都实现
    public interface IBusiness {
    String getXXX();
    String getYYY();
    }
    而这个公司只需要稍微改写一点点即可
    public class A extends B /** where b extends c, c extends d and so on... */
    implements IBusiness {
    public String getXXX() { return doXXX(); }
    public String getYYY() { return doYYY(); }

    //保留
    public void init() {...}
    public void release() {...}
    public String doXXX() {...}
    public String doYYY() {...}
    }

    这样既满足了标准化的要求,又满足了无需修改原来继承A或者使用A的无数个class(有些可能在用户那里,不可能更改)

    假如不用接口,你有两个选择:数典忘祖或者自绝于人

    数典忘祖:
    你的新A必须继承标准化组织的Business,原来a,b, c d...里面的代码全部得重新组织到这个新的A里面,与此同时,那些调用或者继承A的class难保不需要重写

    自绝于人
    原来的就让它去,谁也别再提它了,我们以后就用新的NewA,结果,你的新客户倒是满足了标准化,你的老客户可就 :< :@ :$,而且以后需要维护A和NewA
    定义接口:
    interface Fight{
    void fight();
    }

    肥肥和瘦瘦去实现这个接口:
    class FatFat implements Fight{
    public void fight(){
    System.out.println("FatFat 打人很痛!");
    }
    }

    class ThinThin implements Fight{
    public void fight(){
    System.out.println("ThinThin 打人一点都不痛!!哈哈。");
    }
    }

    然后你可能会这另一个类中使用到FatFat和ThinThin的对象,然后都去执行fight,但是你可能不到运行时就不会知道是具体的那个类的对象,这是你就感谢他们都实现了Fight接口,你可以向上转型,然后通过运行时的多态产生你想要的行为。http://hovertree.com/menu/java/

    Fight a=new FatFat();
    Fight b=new ThinThin();
    a.fight();
    b.fight();
    这样就会执行不同的动作。

    或者如果你有一个方法
    f(Fight i){
    i.fight();
    }

    如果c是实现了Fight接口的其中一个类,那么你就可以这样使用这个方法:
    f(c);
    你不需要知道c究竟是什么对象(不管是FatFat还是ThinThin),你都可以得到你想要的fight动作

    转自:http://hovertree.com/h/bjaf/0c6sbcn8.htm

    推荐:http://www.cnblogs.com/roucheng/p/3504465.html

  • 相关阅读:
    linux 命令——19 find (转)
    linux 命令——18 locate (转)
    linux 命令——17 whereis(转)
    linux 命令——16 which(转)
    linux 命令——15 tail (转)
    linux 命令——14 head (转)
    Java for LeetCode 038 Count and Say
    Java for LeetCode 037 Sudoku Solver
    Java for LeetCode 036 Valid Sudoku
    Java for LeetCode 035 Search Insert Position
  • 原文地址:https://www.cnblogs.com/roucheng/p/javajiekou.html
Copyright © 2011-2022 走看看