Jerry以前在工作中交替做着ABAP和Java开发时,总是在使用一种语言时,怀念另一种语言的便利之处,比如用ABAP开发时,怀念Java里以List为代表的功能强大,使用方便的集合工具类。
List或许是众多Java初学者最先接触和掌握的Java集合工具接口之一。以最具代表性的实现类ArrayList为例,查看其源代码,发现ArrayList不过就是用面向对象的编程方式封装了对一个对象数组的常用操作,使其不仅支持Java原生Array的所有功能,同时也支持前者不具备的动态扩容功能。
对Java稍有了解的开发者,要自己仿照着写出一个同样的ArrayList实现,并不是一件困难的事情。不过List接口和其众多实现类都是Java开发包的一部分,这使得Java开发者做应用开发时不用重复造轮子,可以直接使用,非常方便。
那么SAP ABAP里存在类似的集合工具类么?
首先我们有内表,具备Java Array的所有功能,并且功能和使用灵活度上来说都远胜后者。但内表的操作毕竟是一种面向过程的编程思路。ABAP里存在类似Java List的接口吗?
通过之前查看Java ArrayList的实现源代码,我们可以仿照其思路,在ABAP里实现一个一模一样的ABAP ArrayList出来,只需要定义一个行类型(Table Line)为对象引用的内表变量,再用面向对象编程方式实现对这个内表变量插入,删除,和按索引访问的功能即可。而Java ArrayList的动态扩容,ABAP内表原生就支持。
事实上SAP CRM就采取了这种实现思路,CL_CRM_BOL_ENTITY_COL,这个工具类,从名称上就能判断出它是BOL实例的存储容器,提供了容器内BOL实例元素的插入,删除和遍历的功能。
然而这个列表只能插入类型为BOL实例的元素,有更通用的ABAP List工具类么?那就是CL_OBJECT_COLLECTION, 提供了类似Java ArrayList对列表元素的基本操作:
- 插入
- 删除
- 按索引访问
- 遍历
- 清空列表
这个工具类内部维护的内表类型为TYPE STANDARD TABLE OF REF TO OBJECT, 因此可插入指向任何对象实例的引用。
Jerry这篇博客曾经介绍过该工具类的一个使用例子:
CL_OBJECT_COLLECTION, iterator and Polymorphism
假设我们要开发一个计算图形面积的应用,支持圆形和长方形。实现两个类ZCL_CIRCLE和ZCL_RECTANGLE, 分别按照圆形和长方形的面积计算公式,实现GET_AREA方法。
传统的实现方式
定义一个Table Line类型为通用的对象引用(TYPE REF TO OBJECT)的内表lt_shape,用于存放圆形和长方形的实例对象引用。
每次创建圆形或者长方形的对象实例之后,添加到内表中,然后LOOP内表,逐行取出元素,用IS INSTANCE OF关键字,判断当前记录指向的是圆形还是长方形实例,再用CAST进行强制类型转换,调用对应的面积计算方法。
这种实现方式,在LOOP里有IF ELSE判断,IS INSTANCE OF和CAST这三种非常丑陋的写法。将来如果要支持其他图形比如三角形的面积计算,又得在LOOP里添加新的ELSE分支,这违反了程序设计的开闭原则-对扩展开放,对修改封闭。
采用CL_OBJECT_COLLECTION的多态实现
定义一个新的接口ZIF_SHAPE,圆形和长方形的类均实现自这个接口:
借助CL_OBJECT_COLLECTION, 采取面向对象编程里多态(Polymorphism)的思路,我们不仅避免了丑陋的IF-ELSE,繁琐的类型探测IS INSTANCEOF和强制类型转换CAST,同时将代码行数从37行减少到了20行。将来要是得增加对其他图形的支持,只需要新建图形类并实现,而无需修改下面的计算逻辑。
当然这个例子如果不用CL_OBJECT_COLLECTION, 而是每次把实现了ZIF_SHAPE接口的图形类实例,加入到TABLE LINE类型为TYPE REF TO OBJECT的内表里,然后直接LOOP内表,也可以达到同样的效果。本文只是为了演示CL_OBJECT_COLLECTION的用法,故而没有使用内表来完成计算。
感谢阅读。
要获取更多Jerry的原创文章,请关注公众号"汪子熙":
网友评论