java吧 关注:1,234,743贴子:12,701,878

【治水】接口是干嘛用的

只看楼主收藏回复

首页上全都是水,你们就不怕山洪暴发么
我来点干货填一填
中午休息的时候看了这个帖子
tieba.baidu.com/p/4045115024
休息时间写了这篇帖子,给新手参考
写得匆忙,有各种手误都别见怪
刚才一直忙到现在才想起来还没法出去
抓紧时间摸个鱼,待会蛋疼地去继续整改下一个功能


1楼2015-09-16 14:26回复
    接口是干嘛用的
    接口只规定了对象必须实现的方法,但是没有任何实现,也就是说没有执行逻辑的有效代码。
    要想完成具体业务还是需要编写实现类来实现接口。
    那么问题来了,既然具体业务实现仍然是由接口的实现类来完成的,那么要编写接口有什么卵用?
    先来看看什么样的语言有接口语法
    注意这里说的是编写程序的时候使用的接口语法
    至于其他形式完成接口功能的方式不讨论
    Java有,C++有,C#有
    JavaScript没有,Python没有,Ruby没有
    可以看到需要声明接口的语言都是在传入接口参数时进行语法检查的
    也就是说如果声明了这样一个方法:
    void quest(Httq q);
    那么调用这个方法时只能传入一个参数
    而且这个参数的类型必须是Httq
    当然根据类型转换的原则
    类的子类,接口的实现类也可以
    至于为什么这些语言必须做强制类型检查
    那就是另外的问题了
    好,基于这个事实我们再继续思考
    quest方法只接受Httq类型的参数
    那么我就在Httq类的实现里编写业务逻辑代码就是了啊
    这样当然是可以的,如果Httq类的代码我们可以修改的话
    我们可以假设Httq类里实际上只暴露了一个方法给外界:
    public String getMsg();
    而quest方法中有一行代码是这样写的:
    String msg=q.getMsg();
    这样Httq里承载了某些数据,而getMsg方法就是把它承载的数据
    整理成字符串形式返回
    看起来很简单不是吗?
    有一天我们突然发现,Httq承载数据有不同的格式
    最简单的是纯文本
    有的是字节数组
    有的是xml树形结构
    有的甚至是一个数据库查询结果的链接
    于是我们的getMsg方法中就出现了好多的条件和判断
    这一段用来处理字节数组,另一段用来处理xml
    到目前为止,一切都可以工作的
    然后我们将它打包发布出去了
    一个星期之后,另一个团队基于我们的程序包开发新的功能
    他们发现,Httq类需要承载一个Ajax请求作为数据
    但是他们已经无法再修改Httq类了
    当然他们也是很聪明的
    他们编写了一个HttAjax类继承了Httq类
    覆盖了getMsg()方法
    与此同时HttAjax暴露了一个方法用来获取Ajax数据的版本号
    public String getVersion();
    一切又可以有条不紊地进行了
    镜头拉回我们的团队
    一个月之后
    我们发现了我们已经发布的程序包有重大的安全隐患
    并且第一时间通知了刚才那个Ajax团队
    Ajax团队让我们修复一下然后把新的程序包发布出来
    当然,这正是我们的工作
    所以我们光速修复了安全隐患
    重新制定了字节数组、XML甚至数据库链接的规范
    新的规范要健壮多了
    然后,当然我们也是很人性化的
    为了兼容旧的数据,我们在Httq类里声明了一个方法
    public String getVersion();
    这个方法返回所承载数据的版本号
    用来区别对待新规范和旧规范
    我们满怀诚意的将新版本发布了出去
    第一天一切似乎都很顺利
    第二天Ajax团队报告说过去24小时的数据全部丢失了
    我们检查了我们所有的代码,没有发现问题
    无奈之下,实习生工程师被派到Ajax团队调查问题
    结果是令人沮丧的
    因为HttAjax类覆盖了getVersion()方法
    导致quest方法调用getVersion()时得到了错误的值
    首先我们向Ajax团队建议
    你们把getVersion()改成另一个名字吧
    他们拒绝了,因为他们的代码里到处都有getVersion()的调用
    于是他们把同样的建议返回给了我们
    我们也拒绝了,因为我们的代码里面同样到处都有getVersion()的调用
    这下好了,我们双方都必须花费很多精力重构代码了
    当然,这已经不管我的事,因为我的辞职报告已经交上去了
    我们跳回“看起来很简单不是吗?”这一行
    当我们发现我们要承载不同的数据时
    我们将Httq改成了一个接口
    接口中只声明了一个方法
    public String getMsg();
    我们根据每一种需要承载的数据都编写一个类实现这个接口
    HttqText
    HttqXML
    HttqDB
    和一个又一个的判断说再见吧
    因为对象自己肯定知道自己要处理的是xml还是数据库链接
    妈妈再也不用担心数据类型判断的问题了
    Ajax团队也仅仅只是声明了一个新的类实现了Httq接口
    关于后面出现的安全隐患的问题
    接口是不可以改变的,那我们的getVersion方法怎么办?
    当然,因为HttqText类我们还是可以修改的,不是吗?
    所以我们在HttqText类添加了getVersion()方法
    但是,太奇怪了,quest方法里面却不能调用这个方法
    void quest(Httq q);
    原因很简单,强制类型检查的结果
    Httq是个接口,接口也是类型的一种
    变量q的类型是Httq就可以作为参数传进来
    在方法quest中,变量q指代的仅仅是一个Httq对象
    虽然我们知道Httq接口不可能凭空产生对象
    但是Httq接口里声明了对象q可以调用哪些方法
    因为对象q肯定是一个实现了Httq接口的类的对象
    但是相对的,在quest方法中我们也只知道对象q实现了Httq接口
    它有没有实现其他方法,它是哪个类的对象
    这些只有在运行到此的时候才知道
    所以我们不能这样调用
    //q.getVersion() //这是错误的做法
    因为q不见得是HttqText对象
    那要怎么办,要判断一下对象q的类型吗?
    根本就不用担心因为quest方法也是在一个接口里声明的
    新版本的数据和旧版本的数据根本不是在一个实现类里面处理的!


    3楼2015-09-16 14:29
    收起回复
      技术水


      4楼2015-09-16 14:56
      收起回复
        精品贴前排怒顶


        IP属地:北京5楼2015-09-16 16:35
        收起回复
          技术贴前排留名


          IP属地:湖南6楼2015-09-16 16:47
          收起回复
            前排


            IP属地:浙江来自Android客户端7楼2015-09-16 16:48
            收起回复
              精品技术贴


              IP属地:四川8楼2015-09-16 16:57
              收起回复
                。。。


                来自Android客户端9楼2015-09-16 16:57
                收起回复
                  前排


                  10楼2015-09-16 16:58
                  收起回复
                    太长不看


                    IP属地:河南来自Android客户端12楼2015-09-16 18:36
                    收起回复
                      哇,精品的前排。
                      话说接口是啥?


                      13楼2015-09-16 18:53
                      收起回复
                        尼玛,只能伪前排了


                        IP属地:湖南14楼2015-09-16 18:58
                        收起回复
                          哇(⊙o⊙)哇


                          IP属地:广西来自Android客户端15楼2015-09-16 19:04
                          收起回复
                            精了?


                            IP属地:上海16楼2015-09-16 19:49
                            收起回复
                              看到是精我就进来了


                              IP属地:四川17楼2015-09-16 19:59
                              收起回复