java 接口学习

你应该知道接口是一种契约,它与实现方式无关但是类,即使是抽象类,你都能自定义成员变量,而成员变量往往就与实现方式有关。这一点的实际意义不大。但是有一点,类会暴露太多不必要,甚至不能暴露的东西,你

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

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

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

这一点的实际意义不大。

但是有一点,类会暴露太多不必要,甚至不能暴露的东西,你看一下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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120590.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • next和nextLine的区别

    next和nextLine的区别内容纯属总结,和CSDN上的很多搜索情况内容大致相同,都是正确可靠的。第一种情况:nextline()在前面,next()在后面privatestaticvoidt1(){Strings1,s2;Scannerscanner=newScanner(System.in);System.out.println("请输…

    2022年5月27日
    34
  • 2021年电子设计大赛预测–球形机器人设计方案

    随着2021年电赛的临近和清单的出炉,各参赛队伍都在紧张的备赛当中。然而在电赛清单中,我们能看到一个比较特别的器件–空心透明球。这个器件的特别之处在于它的吃尺寸过大,以至于让人摸不着头脑。在网上看过很多预测,关于这个球的预测大家也是众说纷纭。那么现在就根据预测的最多的一种情况–球形机器人,来进行简单的设计方案分析。准备材料三个直流电机,一个舵机,飞轮一片,空心透明亚克力球(直径在20~30cm),TB6612电机驱动模块两片,STM32F1最小系统板一块,杜邦线若…

    2022年4月7日
    36
  • linux find命令详解_mount命令详解

    linux find命令详解_mount命令详解find命令格式:findpath-option[-print][-exec-okcommand]{}\;find命令的参数:path:要查找的目录路径。~表示$HO

    2022年8月6日
    5
  • 51单片机最小系统解读

    51单片机最小系统解读提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档文章目录前言一、51单片机最小系统模块构成二、电源电路1.电源引脚三、时钟电路1.外部晶振引脚2.晶振(时钟电路)3.时钟电路小tips四、复位电路1.按键复位2.上电复位总结前言在学习51单片机的时候我们最先接触到的就是单片机最小系统,单片机最小系统又叫最小应用系统,顾名思义就是能够使单片机实现简单运行的最少原件的组合。提示:以下将以51单片机最小系统为例进行介绍一、51单片机最小系统模块构成二、电源电路一个系统的

    2022年6月23日
    27
  • 跨域访问解决及原因分析_为什么会有跨域问题

    跨域访问解决及原因分析_为什么会有跨域问题转自:https://www.cnblogs.com/itmacy/p/6958181.html跨域问题:解决跨域的三种方案当前端页面与后台运行在不同的服务器时,就必定会出现跨域这一问题,本篇简单介绍解决跨域的三种方案,部分代码截图如下,仅供参考:方式一:使用ajax的jsonp前端代码 服务器代码 使用该方式的缺点:请求方式只能是get请求方式二:使用jQuery的jsonp插件…

    2022年9月30日
    4
  • [转] 基于C#的波形显示控件的实现

    [转] 基于C#的波形显示控件的实现

    2022年3月3日
    63

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号