透過介面標準化ABAP OO開發
正文
本文是對介面程式設計的討論,希望能對年輕的開發者有所幫助。
要點:
透過介面對類方法進行更高層的抽象
介面使程式碼清晰易讀
介面使你可以建立模擬物件(Mockup Object)以提高程式碼的可測試性
幫助實現
可以在不使用和型別轉換的前提下使用多種類的不同例項。
因為在學習ABAP之前,我曾經學習過其它面嚮物件語言,因此我很糾結於ABAP中不存在的一個特性——過載方法(overload)。
也許你會問,過載是什麼?
過載就是函式或者方法有相同的名稱,但是引數列表和實現不相同的情形。
沒有了過載,在某種程度上,類也許會變的過大,並且難以追蹤那些有著相似行為但是名字不同的方法。
介面不提供過載能力,但是透過限制名字不同但是功能相近的方法的數量,介面可以整理和簡化你的程式碼。
本文連結:http://www.cnblogs.com/hhelibeb/p/8919767.html
英文原文:
簡介
在ABAP中類的繼承是單一繼承(每個類只能有一個父類),介面實現可以有多個。
例如,上圖中的LCL_Child_Class繼承LCL_Parent_Class中所有的非私有變數、方法、型別和常量,並且必須實現LINF_Utility和LINF_Saver介面中所有的功能。
為了解釋介面的定義,我將使用個“不怎麼專業”的描述——它是一個類似於類的實體,不包含所宣告的方法的任何具體實現,但是它可能包含常量、型別和變數。介面無法被初始化。
預設情況下介面的所有方法都必須被實現——這是物件導向程式設計中的一個通常的強制規則。不能允許介面方法的實現變得可選擇,但是這不屬於本文的討論範圍,所以不會展開論述。
(譯註:原文評論指出,在ABAP中,可以使用DEFAULT IGNORE|FAIL附加項指定一個可選的介面方法,雖然好像並沒有什麼用)
“真實”用例
設想下我們有個程式,需要從多種資料來源獲取資料並更新到表SFLIGHT:
Excel上傳
上傳
在程式執行期間上傳修改和插入的行
當然我們可以在該清單中新增ADBC源、經由HTTP客戶端物件抓取的JSON/XML源等,但是我只是想介紹下要點,沒必要窮舉所有例子。
同時,因為本文只是對可能性的表述,因此我不會建立一個能真正工作的程式。
宣告介面
我們將建立2個介面,不過在這個例子裡只有一個是真實需要的。
第一個是最重要的,我命名它為linf_sflight_career,因為這是個用於EXCEL、RFC和本地表運輸(carrier)的本地介面,在本地類中實現。
interface linf_sflight_carrier. types: tt_sflight type standard table of sflight with default key, st_sflight type sorted table of sflight with non-unique key mandt carrid connid, ht_sflight type hashed table of sflight with unique key mandt carrid connid fldate. methods: "! Returns hashed table SFLIGHT contents "! @parameter r_sflight | get_hashed_records returning value(r_sflight) type ht_sflight, "! Returns sorted table SFLIGHT contents "! @parameter r_sflight | get_sorted_records returning value(r_sflight) type st_sflight, "! Returns standard table SFLIGHT contents "! @parameter r_sflight | get_standard_records returning value(r_sflight) type tt_sflight. endinterface.
介面包含不同的表型別和三個方法,將會在EXCEL、RFC和表運輸的類中實現。
下個介面由負責儲存資料到資料庫的類實現:
interface linf_sflight_saver. constants: "! Table lock types begin of lock_types, exclusive type enqmode value 'E', end of lock_types. constants: "! Scopes for table lock begin of scope_range, _2 type char01 value '2', end of scope_range. constants: _sflight type tablename value 'SFLIGHT'. methods: "! Save data from carrier object to SFLIGHT table "! @parameter i_carrier | Carrier object save_data importing i_carrier type ref to linf_sflight_carrier. endinterface.
在這裡,你也許會問,為什麼我們需要這麼多類來完成一個很簡單的工作?為什麼我們不利用相似的類繼承或者是單個類來實現目的?
答案是顯然的:。如果你想要知道關於它的更多資訊,可以留言回覆,我將建立另一篇部落格單獨講這一話題。
回到主題——接下來是類:
class lcl_excel_carrier definition. public section. interfaces: linf_sflight_carrier. aliases: tt_sflight for linf_sflight_carrier~tt_sflight, st_sflight for linf_sflight_carrier~st_sflight, ht_sflight for linf_sflight_carrier~ht_sflight, get_hashed_records for linf_sflight_carrier~get_hashed_records, get_sorted_records for linf_sflight_carrier~get_sorted_records, get_standard_records for linf_sflight_carrier~get_standard_records. protected section. private section. data: standard_sflight type tt_sflight, sorted_sflight type st_sflight, hashed_sflight type ht_sflight. endclass. class lcl_excel_carrier implementation. method get_hashed_records. r_sflight = hashed_sflight. endmethod. method get_sorted_records. r_sflight = sorted_sflight. endmethod. method get_standard_records. r_sflight = standard_sflight. endmethod. endclass.class lcl_rfc_carrier definition. public section. interfaces: linf_sflight_carrier. aliases: tt_sflight for linf_sflight_carrier~tt_sflight, st_sflight for linf_sflight_carrier~st_sflight, ht_sflight for linf_sflight_carrier~ht_sflight, get_hashed_records for linf_sflight_carrier~get_hashed_records, get_sorted_records for linf_sflight_carrier~get_sorted_records, get_standard_records for linf_sflight_carrier~get_standard_records. protected section. private section. data: standard_sflight type tt_sflight, sorted_sflight type st_sflight, hashed_sflight type ht_sflight.endclass.class lcl_rfc_carrier implementation. method get_hashed_records. r_sflight = hashed_sflight. endmethod. method get_sorted_records. r_sflight = sorted_sflight. endmethod. method get_standard_records. r_sflight = standard_sflight. endmethod.endclass.class lcl_table_carrier definition. public section. interfaces: linf_sflight_carrier. aliases: tt_sflight for linf_sflight_carrier~tt_sflight, st_sflight for linf_sflight_carrier~st_sflight, ht_sflight for linf_sflight_carrier~ht_sflight, get_hashed_records for linf_sflight_carrier~get_hashed_records, get_sorted_records for linf_sflight_carrier~get_sorted_records, get_standard_records for linf_sflight_carrier~get_standard_records. protected section. private section. data: standard_sflight type tt_sflight, sorted_sflight type st_sflight, hashed_sflight type ht_sflight.endclass.class lcl_table_carrier implementation. method get_hashed_records. r_sflight = hashed_sflight. endmethod. method get_sorted_records. r_sflight = sorted_sflight. endmethod. method get_standard_records. r_sflight = standard_sflight. endmethod.endclass.
上面的類有著相同的功能,但是根據具體的運輸目的,完整的實現類會有某些特定的方法(比如從raw資料中過濾、檢索資料等等)。
所有運輸類需要實現linf_sflight_carrier——由此我們不再不得不在每個類中定義所有的方法了。不過,我使用aliases關鍵字增加了別名,以提高程式碼的可讀性。
我們下一個將要建立的類是資料庫儲存者,名字是lcl_database_saver:
class lcl_database_saver definition. public section. interfaces: linf_sflight_saver. aliases: lock_types for linf_sflight_saver~lock_types, scope_range for linf_sflight_saver~scope_range, save_data for linf_sflight_saver~save_data, _sflight for linf_sflight_saver~_sflight. protected section. private section. methods: "! Creates table lock key for database lock "! @parameter i_sflight_ref | Reference to SFLIGHT table line "! @parameter r_varkey | Varkey returned create_varkey importing i_sflight_ref type ref to sflight returning value(r_varkey) type vim_enqkey, "! Locks table using passed varkey "! @parameter i_varkey | Table lock key "! @parameter i_tabname | Table name "! @parameter r_subrc | Information on lock creation. 0 = okay lock_table_line importing i_varkey type vim_enqkey i_tabname type tablename default _sflight returning value(r_is_locked) type abap_bool, "! Unlocks locked table line "! @parameter i_varkey | Table lock key "! @parameter i_tabname | Table name unlock_table_line importing i_varkey type vim_enqkey i_tabname type tablename default _sflight. endclass. class lcl_database_saver implementation. method save_data. loop at i_carrier->get_standard_records( ) reference into data(standard_line). data(varkey) = create_varkey( standard_line ). if lock_table_line( i_varkey = varkey ). modify sflight from standard_line->*. unlock_table_line( exporting i_varkey = varkey ). endif. endloop. endmethod. method lock_table_line. call function 'ENQUEUE_E_TABLEE' exporting mode_rstable = lock_types-exclusive " Lock mode for table RSTABLE tabname = i_tabname " 01th enqueue argument varkey = i_varkey " 02th enqueue argument _scope = scope_range-_2 exceptions foreign_lock = 1 system_failure = 2 others = 3. r_is_locked = xsdbool( sy-subrc = 0 ). endmethod. method unlock_table_line. call function 'DEQUEUE_E_TABLEE' exporting mode_rstable = lock_types-exclusive " Lock mode for table RSTABLE tabname = i_tabname " 01th enqueue argument varkey = i_varkey " 02th enqueue argument _scope = scope_range-_2. endmethod. method create_varkey. r_varkey = |{ i_sflight_ref->mandt }{ i_sflight_ref->carrid }{ i_sflight_ref->connid }{ i_sflight_ref->fldate }|. endmethod. endclass.
最後,執行例子:
initialization. data(excel_carrier) = new lcl_excel_carrier( ). data(rfc_carrier) = new lcl_rfc_carrier( ). data(database_saver) = new lcl_database_saver( ).try. database_saver->save_data( i_carrier = excel_carrier ).catch cx_sy_assign_cast_illegal_cast.catch cx_sy_assign_cast_unknown_type.catch cx_sy_assign_cast_error.endtry.try. database_saver->save_data( i_carrier = rfc_carrier ).catch cx_sy_assign_cast_illegal_cast.catch cx_sy_assign_cast_unknown_type.catch cx_sy_assign_cast_error.endtry.
如你所見,透過把抽象部分移動到介面層面,我們可以確保任何實現了linf_sflight_carrier介面的類可以傳輸給saver方法並且被正確處理。
另一個該實現的優點是可以快速簡單地建立模擬物件來進行單元測試。可測試的程式碼即更好的程式碼。
這就是本文的全部內容了,願你喜歡。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1020/viewspace-2800650/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- openGauss 支援標準開發介面
- ABAP OO - ALV_TREE例程
- [譯] 元件化開發利器:Web Components標準元件化Web
- 介面設計標準
- 記錄ABAP開發的日常——SAP_PO開發同步介面案例
- 透過低程式碼開發加速數字化轉型
- 標準IO常用函式介面函式
- 如何透過郵件標題提升EDM轉化率
- 一個基於Java的介面快速開發框架!無需編寫程式碼,透過UI介面編寫介面!Java框架UI
- 小視訊app開發過程中的兩種編碼標準APP
- 資料治理--03資料標準 形成企業自身標準6個文件, 怎麼透過資料標準一步步建表
- Git Commit 標準化GitMIT
- 權威認可!OceanBase 透過分散式資料庫金融標準驗證分散式資料庫
- 透過指標引用陣列指標陣列
- Revive開發商加入VR開源標準OpenXRVR
- autofac aop擴充套件 透過介面套件
- HarmonyOS開發:透過文字生成碼圖
- "零"學習成本:使用 Web 標準開發動態化 Flutter 應用WebFlutter
- 道德標準的形成過程
- 全球首家!騰訊雲率先透過德國C5:2020標準審計
- 標準的開發框架,對企業開發有多重要?框架
- SAP ABAP Netweaver伺服器的標準登入方式講解伺服器
- DevOps邁向標準化,平臺工程讓開發運維更輕鬆dev運維
- 透過API介面實現資料探勘?API
- 硬性測試標準過時?Voodoo採用新的發行KPI指標OdooKPI指標
- 透過標籤清理微信好友:Python自動化指令碼解析Python指令碼
- 國內圖計算標準釋出 悅數圖資料庫透過測試資料庫
- 華為雲區塊鏈三大核心技術國際標準立項透過區塊鏈
- OpenHarmony標準系統開機時長最佳化
- WordPress開發入門09:WordPress編碼標準
- GL Studio — 符合26262 標準的HMI 開發工具
- 支付寶介面對接開發過程
- 標準化/結構化 JSON 輸出JSON
- weblogic JDBC標準化效能最佳化WebJDBC
- weblogic標準化部署大綱Web
- Clang-format格式標準化ORM
- 什麼是特徵標準化特徵
- ABAP BAPI 複製標準專案模板實現專案立項API