ABAP面向对象的开发
在程序中, 對象的識別和尋址是通過對象引用來實現的,對象引用變量可以訪問對象的屬性和方法.
ABAP 中的類也有程序內部的局域類和全局類之分, 其作用范圍不同.
ABAP中的全局類是通過ABAP工作臺中的類創建工具 Class Builder ?SE24開發的, 保存在系統類庫程序 Class Pool 中, 可供所有程序作用.
一. 程序中類的定義.
1. 類聲明及實現
* Class Declarations
CLASS application DEFINITION.
?PUBLIC SECTION.
??? METHODS: show_text.
?PRIVATE SECTION.
???DATA text(100) TYPE c VALUE 'This is my first ABAP Object.'.
ENDCLASS.
?* Class Implementation
CLASS application IMPLEMENTATION.
?METHOD show_text.
???WRITE text.
?ENDMETHOD.
ENDCLASS.
?
2. 成員可見性.
①公有: 可被所有對象使用.
PUBLIC SECTION.
?
②保護: 只能被本類及其派生類中的方法使用.
PROTECTED SECTION.
?
③私有: 只能被類本身的方法所使用.
PRIVATE SECTION.
?
公有部分常常用來定義類的方法, 而類屬性則一般定義為類的私有或保護數據, 只能通過自身或其派生類的方法來操作.
?
3. 成員類型.
可定義三種不同類型的成員, 分別是屬性, 方法和事件.
屬性是在類內部的數據對象, 對于實例屬性, 用 DATA 定義, 語法與數據對象聲明相同;
對于靜態屬性(類屬性), 使用CLASS-DATA 語句定義, 在類的聲明部分定義.
?
* Class Declarations
CLASS application DEFINITION.
?PUBLIC SECTION.
???CLASS-DATA class_name(10) type c value 'Vehicle'.? "靜態屬性
?PRIVATE SECTION.
???DATA speed TYPE i.
ENDCLASS.
對于公有組件還可以在屬性定義語句中增加 READ-ONLY 關鍵字, 則該屬性不能被類外部讀取但可被類的內部方法所修改.
除 DATA 外, 也可以使用 CONSTANT? 語句定義類常量, 必須在類定義時指定其值.
使用 TYPES 語句在類中定義的數據類型, 相當于靜態屬性, 其定義方法與普通 ABAP 程序類似.
類方法需要在類的聲明和實現兩部分進行定義, 在類的聲明部分說明方法的參數接口, 在實現部分則通過 ABAP代碼完成具體的功能.
方法的聲明關鍵字為 METHODS 和 CLASS-METHODS.
METHODS meth
?IMPORTING ... i1 TYPE ...
?EXPORTING ... e1 TYPE ...
?CHANGING? ... c1 TYPE ...
?EXCEPTIONS ... x1 TYPE ...
定義了方法及方法的參數接口, 和 FORM 相似, 但沒有 TABLES 參數.
CLASS vehicle DEFINITION.
?PUBLIC SECTION.
???CLASS-DATA class_name(10) TYPE c VALUE 'Vehicle'.
???METHODS: accelerate,
????????????show_speed.
? PRIVATESECTION.
???DATA speed TYPE i.
ENDCLASS.
CLASS vehicle IMPLEMENTATION.
?METHOD accelerate.
???speed = speed + 1.
?ENDMETHOD.
?METHOD show_speed.
???WRITE:? / 'Speed: ', speed.
?ENDMETHOD.
ENDCLASS.
?
二. 定義系統全局類.
通過 Class Builder 工具在類型為 K 的 ABAP 類庫程序中定義.?
如果在一個程序中使用該類,則整個類庫將被載入到程序內存中.
1. 全局類定義.
可以用 SE80 或 SE24 進入 Class Builder 進行創建.
實例生成:
1、public:決定該類的實例可以被所有的用戶創建。
2、protected:只能被其本身或者派生類創建。
3、private:只能通過其自身的方法創建。
選了“最終”則說明全局類不能在程序中被繼承。
使用全局類.
DATA :?OB_VE? TYPE? REF? TO?Z_CL_VEHICLE .
START-OF-SELECTION .
?? CREATE?OBJECT?OB_VE .
?? CALL? METHOD?OB_VE ->ACCELERATE
?????? .
??CALL?METHOD?OB_VE->SHOW_SPEED.
?
三. 程序中的類實例.
使用對象的步驟如下:
1) 定義類的聲明和實現方法;
2) 使用 DATA 語句中的 TYPE REF TO 參照類類型聲明引用變量;
3) 使用CREATE OBJECT 語句創建對象;
4) 通過 ->或 => 運算符訪問對象或類組件;
?
1. 對象創建與引用;
ABAP 對象的創建和訪問需要通過對象引用進行, 引用類型是ABAP基本類型之一,?
其中包括數據引用和對象引用,
其中對象引用又包括類引用和接口引用.?
對于普通類來說, 應使用類引用.
在程序中, 需要先根據對象類型聲明引用類型變量, 然后對該變量引用ABAP對象, 該引用變量中實際上存儲的是ABAP對象的內在地址,?
因而該引用類型變量也就是普通意義上的指向對象的指針.一個引用類型變量可以不指向任何內存地址或指向一個數據對象,?
但一個ABAP對象則可以同時存在多個指向它的指針, 可以通過所有這些指針對其進行操作.
? DATA ob_vehicle TYPE REF TO vehicle.
? CREATEOBJECT ob_vehicle.
其中DATA語句創建了一個引用數據對象ob_vehicle?, 該數據對象的類型定義為"指向一個類為vehicle的對象的指針".
定義指針之后,CREATE OBJECT 語句則創建了一個類vehicle的實例, 并同時將該對象的地址指針賦給引用類型ob_vehicle.實際情況如下圖所示:
引用類型與其它類型的數據類型相同, 同類型變量之間也可以相互賦值, 成功賦值之后二者將指向相同的對象.
?
2. 訪問對象組件.
對象創建之后, 可以通過指向它的指針(引用變量)對其進行操作. 可以使用的對象組件一般為當前可見的屬性和方法,?
通過引用變量后接運算符 -> 訪問對象組件. -> 即可以訪問類中定義的實例組件又可以訪問靜態組件.?
但對于靜態組件還有另一種訪問方式, 通過類名稱本身=>直接訪問.
oref->comp
其中oref代表引用變量, comp 代表類成員.
class=>comp
其中class代表類名.
由于引用類型變量本身也可以被定義為類屬性, 因而可以出現下述的鏈式訪問結構:
oref1->oref2->comp
或者
class=>oref->comp
上述的兩種運算符是類的外部訪問, 在某些情況下, 對象本身需要知道本身的地址, 可以使用局部引用變量 ME,
該變量隱式的存在于所有的實例方法中, 當方法被調用時, 該變量將包含自身的地址指針, 這種用法稱為對象的自身引用.
3. 刪除對象
對象占據程序內存, 如果有后續程序中不再使用的對象, 應該將其刪除,?
系統對象的刪除操作與引用變量有關, 系統將自動定時進行檢測, 如果一個對象不再被任何變量引用, 則將其刪除, 并釋放其所占的內存,?
這個操作是通過垃圾回收機制來完成的.
垃圾回收機制定時的清除不再使用的對象, 使用 CLEAR 語句初始化所有指向該對象的引用變量或者將引用變量的值改變, 都將觸發回收機制.
?
四. 方法.
1. 參數的定義和傳遞.
類方法的參數接口部分在在類聲明部分通過METHODS語句定義的, 而且該接口不需要在類的實現部分再次出現, 參數接口的詳細語法形式為:
??? METHODSmeth
?????IMPORTING ... [VALUE(i1)|i1] TYPE type [OPTIONAL|DEFAULT def1] ...
?????EXPORTING ... [VALUE(e1)|e1] TYPE type [OPTIONAL] ...
?????CHANGE??? ... [VALUE(c1)|c1] TYPEtype [OPTIONAL|DEFAULT def1] ...
?????RETURNING VALUE(r)
?????EXCEPTIONS ... X1 ...
?
2. 調用方法時, 除去指定為可選的參數之外, 所有的參數都必須傳遞相應的實參值.
? CALLMETHOD [oref->|class=>]meth
?? EXPORTING...? i1 = f1 ...
???????IMPORTING ...? e1 = g1 ...
???????CHANGING? ...? c1 = c1 ...
???????RECEIVING????? r = h
???????EXCEPTIONS ... x1 = rc1 ...
該語句格式適用于包括類內部直接調用, 實例調用(oref->)和靜態調用(class=>)三種情況. 其中參數定義時用IMPORTING選項指定的形參 i 此時將接受 CALL METHOD 語句中用EXPORTING 中傳遞的實參 f; 而用EXPORTING 選項指定的形參 e 此時將通過 IMPORTING 選項傳遞給實參 g.
如果方法中只包含輸入參數, 而沒有輸出參數, 則可以使用下列幾種形式的簡略形式對參數進行調用.
CALL METHOD [oref->|class=>]method().
CALL METHOD [oref->|class=>]method(f).
CALL METHOD [oref->|class=>|method(...i1 = f1...).
?
Example:
CLASS?VEHICLE?DEFINITION.??PUBLIC?SECTION.
????CLASS-DATA?CLASS_NAME(10)?TYPE?C?VALUE?'Vehicle'.
????METHODS:SHOW_SPEED,
??????ACCELERATE?IMPORTING?RATE?TYPE?I.
??PRIVATE?SECTION.
????DATA?SPEED?TYPE?I.
ENDCLASS.
CLASS?VEHICLE?IMPLEMENTATION.
??METHOD?ACCELERATE.
????SPEED?=?SPEED?+?RATE.
??ENDMETHOD.
??METHOD?SHOW_SPEED.
????WRITE:??/?'Speed:?',?SPEED.
??ENDMETHOD.
ENDCLASS.
DATA:?OB_VEH?TYPE?REF?TO?VEHICLE.
START-OF-SELECTION.
??CREATE?OBJECT?OB_VEH.
??CALL?METHOD?OB_VEH->ACCELERATE?EXPORTING?RATE?=?2.
??CALL?METHOD?OB_VEH->ACCELERATE?EXPORTING?RATE?=?2.
??CALL?METHOD?OB_VEH->SHOW_SPEED.
?
方法還可以進行動態調用, 即通過變量對方法名進行指定, 例如下列語句:
? meth = accelerate.
? CALL METHOD ob_veh->(meth).
?
實參的動態傳遞:
? CALL METHOD [oref->|class=>]meth
???PARAMETER-TABLE ptab
???EXCEPTION-TABLE etab.
其中實參必須在程序中放置在兩個特定類型的內表中, 傳遞給方法, 其中參數表ptab可以參照類型組ABAP_PARMBID(行類型)和ABAP_PARMBIND_TAB(表類型)生成;?
異常表etab 可以參照ABAP_EXCBIND(行類型)和ABAP_EXCBIND_TAB(表類型)生成.
?
3. 函數方法.
函數也是一種過程模塊, 其特殊之處是在調用時可以使用操作符(=)來替代過程調用語句, 并可作為操作數直接應用于操作語句中, 因為函數只返回一個唯一的值.?
在ABAP Objects 語法中, 可以用例如函數方法來實現這種函數功能, 形式如下:
??? METHODSmeth
????? IMPORTING... [ VALUE(i1)|i1] TYPE type [OPTIONAL|DEFAULT def1] ...
?????RETURNING VALUE(r).
一個函數方法可以有多個數量的輸入參數, 但只能有一個輸出參數, 且該輸出參數必須為值傳遞而且需要完成限定其類型.
函數方法的調用格式如下:
CALL METHOD [oref->|class=>]meth
? EXPORTING... i1 = f1 ...
?RECEIVING???? r = h.
簡化的調用形式如下:
... [oref->|class=>]method( ) ...
... [oref->|class=>]method(f) ...
... [oref->|class=>]method(... i1 = f1 ...)...
?
CLASS?CIRCLE?DEFINITION.??PUBLIC?SECTION.
????METHODS?GET_AREA?IMPORTING?VALUE(I_RADIUS)?TYPE?I
?????????????????????RETURNING?VALUE(R_SIZE)???TYPE?F.
??PRIVATE?SECTION.
????CONSTANTS?PI?TYPE?F?VALUE?'3.1415926'.
ENDCLASS.
CLASS?CIRCLE?IMPLEMENTATION.
??METHOD?GET_AREA.
????R_SIZE?=?I_RADIUS?**?2?*?PI.
??ENDMETHOD.
ENDCLASS.
DATA:?OB_CIRCLE?TYPE?REF?TO?CIRCLE,
??????AREA??????TYPE?F.
PARAMETERS:?RADIUS?TYPE?I.
START-OF-SELECTION.
??CALL?METHOD?OB_CIRCLE->GET_AREA
????EXPORTING
??????I_RADIUS?=?RADIUS
????RECEIVING
??????R_SIZE???=?AREA.
??WRITE:?/?AREA.
??AREA?=?OB_CIRCLE->GET_AREA(?RADIUS?).
??WRITE:?/?AREA.
?
4. 構造和析構方法.
1). 構造方法是運行時環境自動調用的一種方法, 用于為對象設定一個初始化狀態, 不能在程序運行過程中由程序代碼調用.?
實例構造方法在每一次對象創建的過程中(CREATE OBJECT語句時)被系統調用, 如果在類聲明部分進行聲明, 則需要在實現部分進行代碼實現.
METHODS constructor
? IMPORTING... [VALUE(i1)|i1] TYPE type [OPTIONAL|DEFAULT def1] ...
? EXCEPTIONS... e1 ...
構造方法中不包含任何形式的輸出參數, 其功能只是定義對象狀態, 而不是對其進行改變.
類構造方法屬于靜態方法, 只在程序中被調用一次, 即第一次使用該類時調用,?
該方法也必須在公有部分聲明, 其名稱必須為 CLASS_CONSTRUCTOR.
???CLASS-METHODS class_constructor.
類構造方法不包含接口, 而且在其中只能訪問類的靜態屬性.
?
CLASS?VEHICLE?DEFINITION.??PUBLIC?SECTION.
????CLASS-DATA?CLASS_NAME(10)?TYPE?C?VALUE?'Vehicle'.
????METHODS:SHOW_SPEED,
??????ACCELERATE?IMPORTING?RATE?TYPE?I,
??????CONSTRUCTOR?IMPORTING?I_SPEED?TYPE?I.?"構造函數
??PRIVATE?SECTION.
????DATA?SPEED?TYPE?I?VALUE?0.
ENDCLASS.
CLASS?VEHICLE?IMPLEMENTATION.
??METHOD?CONSTRUCTOR.
????SPEED?=?I_SPEED.
??ENDMETHOD.
??METHOD?ACCELERATE.
????SPEED?=?SPEED?+?RATE.
??ENDMETHOD.
??METHOD?SHOW_SPEED.
????WRITE:??/?'Speed:?',?SPEED.
??ENDMETHOD.
ENDCLASS.
DATA:?OB_VEH?TYPE?REF?TO?VEHICLE.
START-OF-SELECTION.
??CREATE?OBJECT?OB_VEH?EXPORTING?I_SPEED?=?4.?"構造函數
??CALL?METHOD?OB_VEH->SHOW_SPEED.
??CALL?METHOD?OB_VEH->ACCELERATE
????EXPORTING
??????RATE?=?2.
??CALL?METHOD?OB_VEH->ACCELERATE
????EXPORTING
??????RATE?=?2.
??CALL?METHOD?OB_VEH->SHOW_SPEED.
?
五. 繼承
ABAP 所有的類都是默認繼承了系統中的空類OBJECT.
具有一般性的類稱為基類(Superclass),其各個子類稱為派生類(Subclass).
在類定義時, 使用 INHERTING FROM 附加項可以指定派生類和基類之間的繼承關系.
CLASS c2 DEFINITION INHERITING FROM c1.
? ...
ENDCLASS.
ABAP 中的繼承為單一繼承, 即一個類可以有多個派生類, 但只能有一個直接基類.
在繼承過程中各成員的組件可見性如下:
一個派生類中的公有成員包括其本身公有部分定義的成員以及所有基類公有成員, 這些公有成員可以通過選擇運算符"->" 在類外部獲得.
一個派生類中的被保護成員包括其本身被保護部分定義的成員以及所有基類的被保護成員.?
這些成員不能通過組件選擇運算符"->" 在類外部獲得, 但可以在派生類內部使用. 在類外部看, 其行為與類私有成員完全一致.
一個派生類中的私有成員只包括其本身私有部分定義的成員. 這些成員只能在派生類內部使用.
因而, 繼承類和基類的公有成員和被保護成員享有共同的命名空間, 而私有成員則在不同類之間可以出現重名情況.
參照基類聲明的引用變量可以指向其繼承類的對象, 如上圖所示,?
對象 n 是類 Class3的一個實例, 而左側的三個引用變量CREF1, CREF2, CREF3 則分別參數類Class1, Class2, Class3 生成.?
這三個類存在繼承關系. 參考基類聲明的引用變量也可以指向其派生類, 即三個變量均可以指向對象 n,?
但要注意的是 CREF1 只能訪問 Class1 的公有組件, 而 CREF2可以訪問 Class1 和 Class2的公有組件, CREF3 則可以訪問全部類的公有組件.
但特別要注意的是: 盡管基類引用變量可以指向其繼承類對象, 然而反之則被視為錯誤的類型轉換.
?
多態性的繼承實現.
在繼承中, 多態性是通過方法重載及引用變量實現的, 即子類可以重新定義并以不同的方式實現基類中的公有或保護方法, 此時基類中的方法需為實例方法.
在派生類中要這樣聲明:
METHOD meth REDEFINITION.
該方法必須和基類中的方法具有相同的接口, 但可以通過不同的代碼實現.
在方法重載過程中, 如果在派生類內部仍然需要使用基類中的方法, 則可以使用 SUPER 關鍵字來指定其基類.
CALL METHOD?super->meth.
Example:
*&---------------------------------------------------------------------*
*& Report?Z_AF_050
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
?
REPORT?z_af_050.
?
CLASS class1 DEFINITION INHERITING FROMobject.???? "基類
? PUBLICSECTION.
??? METHODS:accelerate,
????????????write_status.
? PROTECTEDSECTION.
??? DATA:speed TYPE i.
ENDCLASS.
?
CLASS plane DEFINITION INHERITING FROM class1.
? PUBLICSECTION.
??? METHODS:rise,
????????????write_status REDEFINITION.??? ????????"多態
? PROTECTEDSECTION.
??? DATAaltitude TYPE i.
ENDCLASS.
?
CLASS ship DEFINITION INHERITING FROM class1.
? PUBLICSECTION.
??? METHODS:write_status REDEFINITION.???????????"多態
ENDCLASS.
?
CLASS class1 IMPLEMENTATION.
? METHODaccelerate.
??? speed =speed + 1.
? ENDMETHOD.
? METHODwrite_status.
??? WRITE: /'Speed:', speed.
? ENDMETHOD.
ENDCLASS.
?
CLASS plane IMPLEMENTATION.
? METHODrise.
??? altitude= altitude + 2.
? ENDMETHOD.
? METHODwrite_status.
???WRITE:? 'Plane:'.
??? CALLMETHOD super->write_status.
??? WRITE: /'Altitude:', altitude.
? ENDMETHOD.
ENDCLASS.
?
CLASS ship IMPLEMENTATION.
? METHODwrite_status.
??? WRITE: /'Ship speed:', speed.
? ENDMETHOD.
ENDCLASS.
?
DATA: plane_ref TYPE REF TO plane.
DATA: ship_ref TYPE REF TO ship.
?
START-OF-SELECTION.
? CREATEOBJECT: plane_ref,
????????????????ship_ref.
? CALLMETHOD: plane_ref->accelerate,
??????????????plane_ref->rise,
??????????????plane_ref->write_status,
??????????????ship_ref->accelerate,
??????????????ship_ref->write_status.
?
抽象類和抽象方法.
一個基類可能包含多個派生類, 但該基類只是作為模板出現的, 并不需要有任何對象作為實例, 則可以將該類聲明為抽象類(Abstract Class).
CLASS class1 DEFINITION ABSTRACT.
...
ENDCLASS.
抽象類不能使用CREATE OBJECT 語句創建類對象, 其主要目的是為了做派生類的模板, 實際使用的對象則依照各個派生類創建.
也可以將方法定義為抽象方法.
METHODS meth ABSTRACT ...
一個抽象方法不能在類本身中實現, 而必須在其派生出的非抽象類中實現. 因而含有抽象方法的類必須定義為抽象類.
?
最終類和最終方法.
最終類(FinalClass), 是不能被繼承的類, 其主要意義在于: 設計過程中, 如果一個類有很多級別的派生類, 則其中公有和被保護成員方法, 隨意改動該類, 很容易造成派生類中的語法和主義沖突. 因而, 如果不希望在程序中繼續對該類進行派生, 則可以定義該類為最終類.
CLASS class1 DEFINITION FINAL.
...
ENDCLASS.
最終方法是不可以重新定義的方法, 不一定出現在最終類中, 但最終類中的所有方法都是最終方法.
METHODS meth ABSTRACT ...
?
六. 接口.
1. 接口的定義與實現.
Interfaces 即可以保證這些類外部看起來具胡一致性,標準化的接口, 又可以在不同的類內部使用不同的實現方法, 而這個具體實現過程是類外部的用戶無需關心的.
接口是一個獨立結構, 可以在其中定義一些成員并在具體類中實現, 其作用是對類中已經定義的成員進行擴展. 實現接口后,接口將成為類的公有成員, 但類可以自行對接口中的方法以其自身特定形式實現. 這樣, 對于用戶來說, 不同的類對象包含相同的操作接口(即接口中定義的成員名稱), 但程序內部的具體實現則根據類的不同而有所區別. 接口是OOP中除繼承之外的另一個主要多態性的實現機制技術.
?
在程序中定義接口.
INTERFACE intf.
? DATA ...
? CLASS-DATA...
? METHOD ...
? ...
ENDINTERFACE.
在接口定義內部可以聲明的成員與類中的成員相同, 但無需注明具體的可見性, 因為具體類中實現的所有接口組件均為公有成員. 同時, 接口定義中也只包含成員聲明部分, 而具體的實現也將在具體類中進行.
?
實現接口.
接口沒有自己的實例, 因而也不需要進行方法實現, 其中方法的實現要通過具體的類進行.
語法格式如下:
CLASS class1 DEFINITION.
? PUBLICSECTION.
??? ...
???INTERFACES: int1, int2.
? ...
ENDCLASS.
在類定義中, 接口的實現只能出現在公有部分, 接口中定義的所有組件都將被添加為該類的公有成員.
接口中的成員通過接口名稱 +" ~ " + 成員方式訪問.intf~comp.
在類的實現部分, 必須包含所有的接口方法實現.
CLASS class IMPLEMENTATION.
? ...
? METHODintf1_imeth1.
??? ...
? ENDMETHOD.
??? ...
? METHODintf2_imeth2.
??? ...
? ENDMETHOD.
? ...
ENDCLASS.
一個接口可以被任意多個不同的類實現, 該接口中定義的成員集在各個類中名稱相同(形成了一個標準接口), 然而各個類中成員的方法的實現方式則可以有差異, 也就形成了多態性. 如果一個類中除接口之外沒有定義任何類自身的公有成員方法, 則接口就成了該類中的全部"外部接口".
?
*&---------------------------------------------------------------------*
*& Report?Z_AF_051
*&
*&---------------------------------------------------------------------*
?
REPORT?z_af_051.
?
INTERFACE status.???? " Define a interface
? METHODSwrite.
ENDINTERFACE.
?
CLASS counter DEFINITION.
? PUBLICSECTION.
???INTERFACES status.
??? METHODSincrement.
? PRIVATESECTION.
??? DATAcount TYPE i.
ENDCLASS.
?
CLASS counter IMPLEMENTATION.
? METHOD status~write.?????????? " 在接口的實現部分以 stauts~write 實現.
??? WRITE: /'Count in counter is ', count.
? ENDMETHOD.
? METHODincrement.
??? ADD 1 TOcount.
? ENDMETHOD.
ENDCLASS.
?
CLASS bicycle DEFINITION.
? PUBLICSECTION.
???INTERFACES status.
??? METHODSdrive.
? PRIVATESECTION.
??? DATAspeed TYPE i.
ENDCLASS.
?
CLASS bicycle IMPLEMENTATION.
? METHODstatus~write.
??? WRITE: /'Speed of bicycle is', speed.
? ENDMETHOD.
? METHODdrive.
??? ADD 10 TOspeed.
? ENDMETHOD.
ENDCLASS.
?
DATA: count TYPE REF TO counter,
????? bikeTYPE REF TO bicycle,
????? statusTYPE REF TO status,
?????status_tab TYPE TABLE OF REF TO status.
?
START-OF-SELECTION.
? CREATEOBJECT: count, bike.
? DO 5 TIMES.
??? CALLMETHOD: count->increment,
????????????????bike->drive.
? ENDDO.
?
? APPEND:count TO status_tab,
?????????bike TO status_tab.
?
? LOOP ATstatus_tab INTO status.
??? CALLMETHOD status->write.
? ENDLOOP.
該例中包含兩個完全無關的類 bike 和 count, 但實現了相同的接口 status, 因而這兩個類都包含同樣的方法 write, 該方法是在接口中定義的.
?
接口引用.
引用變量是訪問 ABAP 對象的途徑, 與基于類聲明的引用變量類似, 也可以基于接口聲明引用變量, 即接口引用. 接口引用也是一種對象引用, 對于包含接口的類對象, 除通過類引用訪問之外, 還可通過接口引用進行訪問. 接口引用可以指向任何實現了該接口的對象.
YPTES|DATA iref TYPE REF TO intf.
其中 intf 是全局或程序中已經定義的接口.
?
通過接口引用訪問對象.
要訪問一個類對象, 必須先聲明一個基于該類的引用變量, 如果該類為一個接口的實現, 則可以將該車胎變量賦給一個接口變量, 此時接口引用與類引用指向相同的類對象.
假設接口變量名稱為 inef,類引用名稱為 cref, 賦值語法格式如下:
iref = cref.
使用類引用訪問:
cref->intf~attr.
CALL METHOD cref->intf~meth.
使用接口引用訪問屬性和方法的語法格式如下:
iref->attr.
CALL METHOD iref->meth.
對于接口中定義的靜態成員, 如果該成員是常量, 則只能通過接口引用進行訪問:
intf=>const
對于其他靜態接口成員, 則可以通過實現該接口的類本身或者類引用進行訪問:
class=>intf~attr.
CALL METHOD class=>intf~meth.
?
在接口引用間賦值.
與類引用類似, 可以將接口引用分配給不同的引用變量, 還可以在類引用和接口引用之間相互賦值.
假設存在類引用 cref 和接口引用iref, iref1 和 iref2.
iref1 = iref2.
系統將進行靜態語法檢查, 這兩個接口必須參照同一個接口聲明, 或者 iref2 所參照的接口是接口 iref1 的一個成員.
如果使用形式:
iref = cref.
則 cref 參照的類必須是 ABAP 預定義的空類 OBJECT.
對于所有其他情況, 則必須通過強制賦值語句或者強制賦值運算符 "?="進行.
MOVE iref to cref.
cref ?= iref.
在進行強制賦值時, 系統不會出現任何靜態語法檢查, 但系統將在運行時檢查目標對象引用變量是否可以指向源變量引用的對象. 如果允許則進行賦值, 否則將觸發可以捕獲的運行時錯誤MOVE_CASE_ERROR.
如果將接口引用賦給類引用, 且該類不是參照OBJECT聲明,則必須使用強制賦值, 要使賦值過程成功, 接口引用 iref所指向的對象中必須與類引用cref參照的類相同.
?
七 事件.
事件是除去屬性, 方法之外的第三類成員. 這三種組件中, 屬性用于刻畫類對象的狀態, 方法用于訪問或修改對象狀態, 而事件則用于一個類對象發布其狀態的改變, 因而其他對象可以捕獲該方法并作出響應.
在ABAPObject 中, 事件的觸發和處理是通過特定的方法進行的, 一個方法作為觸發者觸發事件, 而程序中的另一個方法則作為處理者捕獲并處理該事件, 處理方法在事件出現進被執行.
?
聲名事件.
事件可以在類或接口的聲名部分進行聲明.
EVENTS|CLASS-EVENTS evt
? EXPORTING... VALUE(e1) TYPE type [OPTIONAL] ...
聲明該事件時, 可以使用 EXPORTING 附加項指定需要向事件處理方法中傳遞的參數, 該參數傳遞方法恒為值傳遞. 實例事件總是包含一個隱含的參數 SENDER, 該參數的類型為觸發事件的類或接口的對象引用.
?
觸發事件.
一個實例事件可以被類中的任意方法觸發, 靜態事件則可以被靜態方法觸發.
RAISE EVENT evt EXPORTING ... e1 = f1 ...
對于每一個沒有被指定OPTIONAL 項的形參 ei, 均必須在實例方法中傳遞一個實參 fi, 自身引用 ME 對象在被默認的傳遞到隱含參數 SENDER.
?
事件處理方法
事件需要通過方法捕獲事件并進行處理, 必須首先為該事件定義一個事件處理方法, 然后在運行時為該事件進行注冊.
聲明事件處理方法
任何類都可以為其它類中定義的事件進行處理, 同時也可以為自身事件進行處理.
實例事件處理方法的語法格式如下:
METHODS|CLASS-METHODS
? meth FOREVENT evt OF cif IMPORTING ... ei ...
一個事件處理方法的接口中只能包含定義在事件 evt 中的形式參數, 并需遵循事件中的參數屬性設定, 但事件處理方法不需要使用所有 RAISE EVENT 中定義的參數.
?
注冊事件處理方法.
要使事件處理方法能夠對事件進行響應,必須在運行時為相關事件注冊該方法, 語法格式如下:
SET HANDLER ... hi ... [FOR] ...
該語句將處理方法和相關的觸發方法進行鏈接, 其語法和使用效果部分地取決于事件的類型.
定義在類中的實例事件.
定義在接口中的實例事件.
定義在類中的靜態事件.
定義在接口中的靜態事件.
對于實例事件, 在進行處理之前必須在注冊語句中使用附加項 FOR 指定希望注冊到的對象.
可以指定一個單獨的對象作為事件觸發者.
SET HANDLER ... hi ... FOR ref.
或者使用 FORALL INSTANCES 附加項為處理器注冊所有可以觸發該事件的實例;
SET HANDLER ... hi ... FOR ALL INSTANCES.
該注冊過程可以作用于目前尚未被創建的實例.
對于靜態事件, 則不能使用 FOR 附加項;
SET HANDLER ... hi ...
該注冊自動應用于整個類, 對于接口中的靜態事件, 該注冊可以應用于目前尚未裝載至內在中的類.
?
事件處理時間.
在程序執行到 RAISEEVENT 語句之后, 所有已注冊的處理方法都將在下一個語句之前被處理. 如果處理方法本身觸發事件, 則該處理方法在原方法繼續執行之前被重新調用.
?
事件的觸發及處理.
事件的觸發和處理基本過程如下: 假設有兩個類 C1 和 C2, C1中包含事件 E1, 而該事件可能在方法 M1 中通過 RAISE EVENT 語句被觸發, 而 C2 中將包含方法 M2, 該方法可以捕獲事件 E1, 并進行處理.
在實際操作時, 要使一個對象的事件處理方法能夠捕獲另一個對象觸發事件, 必須先使用 SET HANDLER 語句進行注冊, 這個注冊過程中形成了觸發對象和響應對象之間的對應關系.
當然, 也可以同時注冊多個處理對象與一個觸發對象相對應.
SET HANDLER 語句則創建一個系統內部的事件處理表, 為每一個事件注冊相應的方法. 該表為系統隱含. 對于實例事件, 事件處理表中包含用于實現處理的方法名稱以及注冊了的類實例引用, 該表通過 SET HANDLER 語句動態的進行維護. 對于靜態事件, 系統為相關類創建一個實例無關的處理表. 一旦事件被觸發, 系統將查找相關的事件表并執行對應于該事件的實例方法.
?
*&---------------------------------------------------------------------*
*& Report?Z_AF_052
*&
*&---------------------------------------------------------------------*
?
REPORT?z_af_052.
?
CLASS class1 DEFINITION INHERITING FROM object.
? PUBLICSECTION.
??? EVENTS:too_fast.??????????? " 聲明事件,如果有參數恒為值傳遞
??? METHODS:accelerate,
????????????show_speed.
? PROTECTEDSECTION.
??? DATA:speed TYPE i.
ENDCLASS.
?
CLASS class1 IMPLEMENTATION.
? METHODaccelerate.
??? speed =speed + 1.
??? IF speed> 5.
????? RAISEEVENT too_fast.???? "觸發事件
????? speed =5.
??? ENDIF.
? ENDMETHOD.
? METHODshow_speed.
??? WRITE: /'Speed:', speed.
? ENDMETHOD.
ENDCLASS.
?
*事件需要通過方法捕獲事件并進行處理,必須首先為該事件定義
*一個事件處理方法,然后在運行時為該事件進行注冊.
*聲明事件處理方法,任何類都可以為其他類中定義的事件進行處理,
*當然也可以為自身事件進行處理.
CLASS handler DEFINITION.
? PUBLICSECTION.?????????
??? METHODShandle_excess FOR EVENT too_fast OF class1.
ENDCLASS.
?
CLASS handler IMPLEMENTATION.
? METHOD handle_excess.
??? WRITE: /'Speed can not be too fast.'.
? ENDMETHOD.
ENDCLASS.
?
DATA: o_class1 TYPE REF TO class1,
?????o_handle TYPE REF TO handler.
?
START-OF-SELECTION.
? CREATEOBJECT: o_class1,
????????????????o_handle.
*要使事件處理方法能夠對事件進行響應,? 必須在運行時為相關事件注冊該方法.
? SET HANDLERo_handle->handle_excess FOR ALL INSTANCES.
?
? DO 11TIMES.
??? CALLMETHOD o_class1->accelerate.
??? CALLMETHOD o_class1->show_speed.
? ENDDO.
總結
以上是生活随笔為你收集整理的ABAP面向对象的开发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ABAP-DOI技术的优化
- 下一篇: vbe6ext.olb不能被加载解决方案