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的用法,故而沒有使用内表來完成計算。
感謝閱讀。