重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。
1、前言
学习Java
的同学们都必然会逃不过学习接口
这一部分的知识。在学习过程中,难免会遇到一些难点或疑问。为了帮助大家更好的理解接口
相关知识,希望这篇文章能帮到一些同学对接口
有彻底的理解。
2、入门
先来看一下接口的面貌,下面建立了一个打印接口,实现这个接口需要实现其打印方法:
// 打印接口。
public interface Printer {
// 需要被实现的打印方法。
void doPrint();
}
// Microanswer品牌的打印机,实现这个接口:
public class MicroanswerPrinter implements Printer{
// 实现打印机具体的打印方式。
public void doPrint() {
System.out.println("打印...");
}
}
也许大家学完了接口之后,对接口
的理解就是:使用interface
声明,任何实现了某个接口的类都必须实现该接口中所有的方法。不得不承认,这的的确确是接口开发的规范,而且也是必须做到这一点的。
但是,疑问点往往不是这么一套限定的开发规则,而是:这东西写起来复杂,看起来扯蛋,想起来还感觉多余,但为什么它又占据了书本中不小的篇幅,为什么大佬们的程序里接口处处可见,难道就是为了彰显自己的技术过硬吗?
针对这些,不得不对接口有个更加简单的、不同于书面教材的解释来解答了。
3、变通
如果一味的将interface
直接翻译成接口
,虽然它的意思的确是接口,但是个人认为这样给初学者来听还是有点不妥!如果换一种理解方式,可能会稍显简单:
我这样说:interface
是一本规则书,如果有某类想要使用,不好意思,请按我书里的规定,实现每一条定律。
结合场景:
公司老总要求生产一台打印机,但是不知道怎么具体去实现,可需要些什么功能,老总倒是心知肚明得很,老总就写了一个
说明书
,叫下面的员工都按照这说明书上的功能去实现,
如上,接口往往开发人员要写的,而是设计这个产品的人需要什么功能而定义出来的,你不用为了特意写某个类而去为这个类写一个接口,应该是为某个接口而去写这个类。老总定义的这个接口,下面的人只要实现就可以了。这可以说是接口存在的理由之一
另一个场景:
小码想开发一个计数器,可以指定要计数多少,每秒钟计数加1,当到达指定计数值的时候,就会发出提示。小码为难了,因为小码想:“计数到了之后,要提示给别人,但是我要怎么提示呢?由于我不知道人家的类是要怎么去接受消息,也就没法推给别人,我为这个功能为难了好久!”。
这样简单的应用场景,或许你会说,这个接口
有什么关系,没有接口也能实现。的确可以不依赖接口,但如果加入接口,会使程序更加灵活。
首先我们不能一味的去迎合别人的程序有哪些方法,而且你在绝大多数情况下,都是不知道别人有什么方法的,为了保证你的程序的原子性,绝对不能介入别人的程序的逻辑。既然是我开发的计数器,别人要使用,你要想:应该别人去迎合我的程序,而不是我去迎合别人。有时候,甚至在同一个程序里不同的功能模块,你也需要这样的想法。
4、应用
这里讲述了接口最常用的场景的实现方案,就拿上面的计数器来说,咱们可以很轻松的写出下面的代码:
public class Counter {
// 调用此方法,传入计数值,开始计数。
public void start(int count) {
for(int i = 0; i < count; i++) {
Thread.sleep(1000); // 每隔1秒计数1次。
}
// 计数完成,发出提示。
}
}
简单的示例代码十分好理解,那如何要在计数完成发出提示位置给别人提示呢?这时候,就要把:要别人去迎合我 这种思想拿出来了。
为了让别人迎合我,我制定一个规则,这个规则就是,要接到我计数完成的提示,就得实现我的规则,这里的规则,用接口
是一个完美的解释!
public class Counter {
// 调用此方法,传入计数值,开始计数。
// 接收到什么时候计数完成,请传入定义的规则。
public void start(int count, CounterEnd counterEnd) {
for(int i = 0; i < count; i++) {
Thread.sleep(1000); // 每隔1秒计数1次。
}
// 计数完成,发出提示。
counterEnd.onEnd();
}
// 定义计数完成时提示的规则
public interface CounterEnd {
// 规则方法。
void onEnd();
}
}
我在 start 方法多加了一个参数,CounterEnd, 它正好是由接口定义的。结合咱们之前的认识:实现接口必须实现里面的方法。那么:任何想要使用我的计数器的类,
在调用start方法的时候,它们只要传入一个 按规则
实现好了的类,就可以在这个类里拿到什么时候计数完成的提示了。我作为计数器,不需要关心别人是怎么做的,
别人要用我,自然会关心我应该怎么去整合到他们的代码里。这就优雅的让我不必关心别人的程序逻辑,也能安心的发布我自己的程序了。
例如有下面计数器使用方法:
public static class Test {
public static void main(String[] args){
Counter counter = new Counter();
// 由于我希望获得计数器计数完成的提示,所以我要实现计数器提供的 "规则";
CounterEnd ender = new CounterEnd() {
public void onEnd() {
System.out.println("计数器计数完成!");
}
};
// 开始计数。
counter.start(20, ender);
}
}
5、总结
接口运用,最广泛的地方莫过于本文的场景2的需求了,这其实就是大老们常说的回调,如果对回调需要了解更多,可以参考下一篇文章: