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

  • 相关阅读:
    测试管理工具
    测试用例--zy
    测试计划和测试用例
    测试用例
    软件测试基础
    异步任务 ---- django-celery
    图片验证码接口
    测试作业
    数据库原理
    HTTPS原理
  • 原文地址:https://www.cnblogs.com/roucheng/p/javajiekou.html
Copyright © 2011-2022 走看看