一文理解Java的抽象特性

抽象(Abstraction)

讲完了Java封装特性,我们再来看Java抽象特性。封装主要讲的是如何隐藏信息、保护数据,而抽象讲的是如何隐藏方法的具体实现,让调用者只需要关心方法提供了哪些功能,并不需要知道这些功能是如何实现的。

在面向对象编程中,我们常借助编程语言提供的接口类(比如 Java 中的 interface 关键字语法)或者抽象类(比如 Java 中的 abstract 关键字语法)这两种语法机制,来实现抽象这一特性。

这里,我们用 “接口类” 特指编程语言提供的接口语法。

对于抽象这个特性,我举一个例子来进一步解释一下。

public interface IPictureStorage {

  void savePicture(Picture picture);

  Image getPicture(String pictureId);

  void deletePicture(String pictureId);

  void modifyMetaInfo(String pictureId, PictureMetaInfo metaInfo);

}

public class PictureStorage implements IPictureStorage {

  //... 省略其他属性...

  @Override

  public void savePicture(Picture picture) { ... }

  @Override

  public Image getPicture(String pictureId) { ... }

  @Override

  public void deletePicture(String pictureId) { ... }

  @Override

  public void modifyMetaInfo(String pictureId, PictureMetaInfo metaInfo) { ... }

}

在上面的这段代码中,我们利用 Java 中的 interface 接口语法来实现抽象特性。调用者在使用图片存储功能的时候,只需要了解 IPictureStorage 这个接口类暴露了哪些方法就可以了,不需要去查看 PictureStorage 类里的具体实现逻辑。

实际上,抽象这个特性是非常容易实现的,并不需要非得依靠接口类或者抽象类这些特殊语法机制来支持。换句话说,并不是说一定要为实现类(PictureStorage)抽象出接口类(IPictureStorage),才叫作抽象。即便不编写 IPictureStorage 接口类,单纯的 PictureStorage 类本身就满足抽象特性。

之所以这么说,那是因为,类的方法是通过编程语言中的 “函数” 这一语法机制来实现的。通过函数包裹具体的实现逻辑,这本身就是一种抽象。调用者在使用函数的时候,并不需要去研究函数内部的实现逻辑,只需要通过函数的命名、注释或者文档,了解其提供了什么功能,就可以直接使用了。比如,我们在使用 C 语言的 malloc () 函数的时候,并不需要了解它的底层代码是怎么实现的。

抽象这个概念是一个非常通用的设计思想,并不单单用在面向对象编程中,也可以用来指导架构设计等。而且这个特性也并不需要编程语言提供特殊的语法机制来支持,只需要提供 “函数” 这一非常基础的语法机制,就可以实现抽象特性、所以,它没有很强的 “特异性”,有时候并不被看作面向对象编程的特性之一。

抽象的意义

实际上,如果上升一个思考层面的话,抽象及其前面讲到的封装都是人类处理复杂性的有效手段。在面对复杂系统的时候,人脑能承受的信息复杂程度是有限的,所以我们必须忽略掉一些非关键性的实现细节。而抽象作为一种只关注功能点不关注实现的设计思路,正好帮我们的大脑过滤掉许多非必要的信息。

除此之外,抽象作为一个非常宽泛的设计思想,在代码设计中,起到非常重要的指导作用。很多设计原则都体现了抽象这种设计思想,比如基于接口而非实现编程、开闭原则(对扩展开放、对修改关闭)、代码解耦(降低代码的耦合性)等。

换一个角度来考虑,我们在定义(或者叫命名)类的方法的时候,也要有抽象思维,不要在方法定义中,暴露太多的实现细节,以保证在某个时间点需要改变方法的实现逻辑的时候,不用去修改其定义。举个简单例子,比如 getAliyunPictureUrl () 就不是一个具有抽象思维的命名,因为某一天如果我们不再把图片存储在阿里云上,而是存储在私有云上,那这个命名也要随之被修改。相反,如果我们定义一个比较抽象的函数,比如叫作 getPictureUrl (),那即便内部存储方式修改了,我们也不需要修改命名。

发表评论

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

关注我们