通过阅读 SpringCloud 源码 来 理解接口和抽象的区别
大家好,我是悟空呀。
我们通过阅读 Spring Cloud 源码来理解下 Java 中的接口和抽象的区别。
我们最熟悉的应该是这个:接口中定义的方法,不能自己实现,必须由实现类来实现,抽象类中可以包含已实现的方法。
关于接口的一些特性
首先我们看下接口有哪些特性。我们用接口的话,无非就是用 interface 来定义。比如我们在使用 OpenFeign 组件时,都会这样定义一个 FeignClient,用来远程调用的。
然后接口中,我们是见不到属性的,只能声明方法。比如在 OpenFeign 源码中,我们可以看到接口是这样定义的,只有一个方法。而且方法是没有方法体的。
然后当类实现接口的时候,必须实现接口中的所有方法。在 IDEA 工具中,如果没有实现接口中定义的所有方法,将会提示错误。我们可以直接用 IDEA 的提示,来一键生成接口的所有实现方法,非常方便。
关于抽象的一些特性
抽象类无非就是用 abstract
修饰起来。比如在 OpenFeign 源码中就有用到抽象类。
然后这个抽象类里面定义了一个抽象方法:
然后有一个类继承这个抽象类:
然后这个类通过 @Override
注解重写了抽象接口:
另外抽象类 Feign 是可以有自己的方法实现的,比如这个方法 configKey
:
然后抽象类 AsyncFeign 里面还可以自定义属性:
根据上面的例子,我们总结下:
首先抽象类是不允许被实例化,也就是不能 new Feign()。
然后抽象类是可以包含属性的,方法也可以有实现的,也有需要子类来实现的抽象方法,比如上面的 newInstance 方法。当子类继承抽象类时,必须实现抽象类中的所有抽象方法。
一开始接触抽象类时,会感觉很奇怪,为什么需要抽象类呢?这不是把问题弄复杂了吗?抽象类还多了一个层级呢。
抽象类带来的好处
首先,抽象类带来的很大的作用就是实现代码复用,比如当有多个子类有相同的属性或方法时,我们可以抽象出一个公共的类,然后子类继承这个抽象类,当然,这个公共类可以是普通父类,也可以是抽象类。
但是抽象类中的方法可以交给子类去实现,让子类有不同的功能。
另外呢,因为抽象方法必须由子类来实现,所以可以规范开发,防止开发人员忘记实现抽象方法。
接口带来的好处
首先我们总是听到:多用组合,少用继承。这个组合代表的意思就是用多个接口来实现不同类的功能。
比如鸵鸟和麻雀都属于鸟类,如果我们抽象出了一个 Bird 类,然后鸵鸟和麻雀都继承 Bird 类。然后 Bird 类有一个抽象方法:fly(),但是鸵鸟是不会飞的,它实现这个方法根本没有意义。
但是有同学就会说了,何不抽象出两个类:会飞的 Bird 类和不会飞 Bird 类。然后鸵鸟继承不会飞的鸟类,不就可了吗?
但是你想想,如果再增加一种情况,会不会抓鱼,那排列组合是不是就有四种抽象类了?如:
会飞会抓鱼抽象类。
会飞不会抓鱼抽象类。
不会飞会抓鱼抽象类。
不会飞不会抓鱼抽象类。
但是如果我们用接口就方便多了,我们定义了会飞接口,会抓鱼两个接口,不同的鸟类继承相关接口就可以了。
另外就是在远程调用框架中用得非常多,调用者只需要关注抽象的接口,不需要了解具体的实现,具体的实现代码对调用者透明。接口实现了约定和实现相分离,降低了代码间的耦合性,提高代码的可扩展性。
好了,接口和抽象的内容就总结到这里了,不知道各位在工作中用抽象多还是接口多呢?
作者简介:悟空,8 年一线互联网开发和架构经验,用故事讲解分布式、架构设计、Java 核心技术。《JVM 性能优化实战》专栏作者,开源了《Spring Cloud 实战 PassJava》项目,公众号:悟空聊架构
。本文已收录至 www.passjava.cn
版权声明: 本文为 InfoQ 作者【悟空聊架构】的原创文章。
原文链接:【http://xie.infoq.cn/article/4545c959376f401dcd1510f21】。未经作者许可,禁止转载。
评论