文章目录
ABAP中面向对象的元素:类(Classes),接口(interfaces),对象(objects),继承(inheritance).
类:是一种数据结构,模拟现实中存再的对象和关系,包含静态的属性和动态的方法。
一 类
1.1类
1.1.1类的定义;
CLASS/ENDCLASS
CLASSIMPLEMENTATION
METHOD … ENDMETHOD.
…
ENDCLASS.
1.1.2.类成员:实例成员;静态成员;
声明实例成员:DATA 或METHOD来声明(->)。
声明静态成员:CLASS-DATA CLASS-METHOD(=>).
1.1.3.类成员可见性;
public section :公共部分
protected section : 保护部分
private section: 私有部分
1.1.4.类在ABAP程序中的使用;
1.声明类开定义类的使用方法。
2.data type ref to ()
3. create object
4. -> =>运算符号类对象或组件;
1.1.5.Demo;
REPORT zjgltest01.
" 创建类一
CLASS callobj DEFINITION.
PUBLIC SECTION. " 定义公共类成员
CLASS-DATA:para(30) TYPE c VALUE 'The static class parameter!'. " 定义静态变量
DATA count TYPE i. " 定义该类中的全局变量
METHODS : showdata1,
showdata2.
PRIVATE SECTION. "定义类中私有成员.
METHODS:showdata3.
ENDCLASS.
" 定义类方法实现行为
CLASS callobj IMPLEMENTATION.
METHOD showdata1.
WRITE:'HELLO SAP'.
ENDMETHOD.
METHOD showdata2.
count = 1.
WRITE:count.
CALL METHOD showdata3. " 在类内啊调用私有方法
ENDMETHOD.
METHOD showdata3.
WRITE:/'The Private Method!'.
ENDMETHOD.
ENDCLASS.
" 定义第二个类,其成员对象为一静态方法
CLASS callobj2 DEFINITION.
PUBLIC SECTION.
CLASS-METHODS:call_static_class.
ENDCLASS.
" 定义第二个类方法
CLASS callobj2 IMPLEMENTATION. " 直接引用其它类中的静态变量
METHOD call_static_class.
WRITE:/ callobj=>para.
ENDMETHOD.
ENDCLASS.
" 主程序
DATA obj TYPE REF TO callobj. " 引用参照类声明变量
DATA : methname TYPE string. " 定义方法名变量
START-OF-SELECTION.
CREATE OBJECT obj. " 创建类实例化对象
methname = 'SHOWDATA2' . " 为变量赋值方法名
CALL METHOD : obj->showdata1, " 调用类方法
OBJ->(methname). " 通过变量调用类方法
CALL METHOD:callobj2=>call_static_class." 无需实例化
1.1.6 总结.
由于是在定义中,所有showdata2里可以引用showdata3.
1.2.类方法的声明及属性
1.2.1描述
方法是对象行为的实现部分,为类中的过程。类方法需要在声明和实现两部分进行定义,在类的声明部分说明方法的接口参数,在类的实现部分则通过ABAP参数完成具体功能。类中所定义变量与主程序中所定义变量是独立分开的,但不能有HEADER LINE的内表。
方法声明关键字:METHOD 或 CLASSS-METHOD.
方法实现代码: METHOD…ENDMETHOD.
1.import/Export:输入,输出接口,其接口参数可以为单个变量,Structure,要么内表 .
2.Changing:可同时作为输入,输入接口,其参数与上面一样。
3.RETURNING:返回类传递数值()。
4.EXCEPTIONS:返回执行中所有出现的错误。
1.2.2 demo
REPORT zjgltest02.
CLASS CALLOBJ DEFINITION.
PUBLIC SECTION. " 定义可公用的结构休,内表及方法
DATA : BEGIN OF L_STRUC,
NAME(10) TYPE C,
END OF L_STRUC.
" 不能用hearder line的内表
DATA:LTAB LIKE TABLE OF L_STRUC INITIAL SIZE 0.
METHODS:SET IMPORTING VALUE(SET_VALUE) LIKE LTAB, " 定义传入内表,自定义类方法名'SET'
GET EXPORTING VALUE(GET_VALUE) TYPE I, " 自定义类方法名“GET”
CHG CHANGING VALUE(CHG_VALUE) TYPE I. " 自定义类方法名"CHG"
ENDCLASS.
" 对于同一个类方法可同时使用多个参数
CLASS CALLOBJ IMPLEMENTATION .
METHOD SET.
LOOP AT SET_VALUE INTO L_STRUC.
WRITE:/ L_STRUC.
ENDLOOP.
ENDMETHOD.
METHOD GET.
GET_VALUE = 20.
ENDMETHOD.
METHOD CHG.
CHG_VALUE = CHG_VALUE + 20.
ENDMETHOD.
ENDCLASS.
DATA OBJ TYPE REF TO callobj.
DATA NUM TYPE I.
DATA : L_STRUC LIKE CALLOBJ=>L_STRUC. " 参考类变量定义相关结构体及内表
DATA : LTAB LIKE CALLOBJ=>LTAB.
START-OF-SELECTION.
CREATE OBJECT OBJ.
L_STRUC-NAME = 'JARY'. APPEND L_STRUC TO LTAB. " 自定义数据
L_STRUC-NAME = 'PLATO'. APPEND L_STRUC TO LTAB.
L_STRUC-NAME = 'JASSON'. APPEND L_STRUC TO LTAB.
CALL METHOD: OBJ->SET EXPORTING SET_VALUE = LTAB,
OBJ->GET IMPORTING GET_VALUE = NUM.
WRITE:/ NUM.
CALL METHOD:OBJ->CHG CHANGING CHG_VALUE = NUM.
WRITE:/ NUM.
1.3类函数定义及使用
类可以定义为函数并为外部程序调用 .一个类函数可以有多个输入参数,但只能有一个输出参数。类的输出接口参数必须与类函数中所定义类型保持一致。
1.3.1 Damo
REPORT zjgltest02.
CLASS ball DEFINITION.
PUBLIC SECTION.
CONSTANTS pi TYPE f VALUE '3.14'.
METHODS: get_volumn IMPORTING VALUE(radius) TYPE i
RETURNING VALUE(volumn) TYPE f.
ENDCLASS.
CLASS ball IMPLEMENTATION.
METHOD get_volumn.
volumn = 4 * pi * radius * radius * radius / 3.
ENDMETHOD.
ENDCLASS.
DATA:volumn TYPE f,
ball_obj TYPE REF TO ball.
DATA:res TYPE p DECIMALS 2.
PARAMETERS:radius TYPE i.
START-OF-SELECTION.
CREATE OBJECT ball_obj.
volumn = ball_obj->get_volumn( radius ).
MOVE volumn TO res.
WRITE: /res.
1.3.2 总结
get_volumn( radius ):一定要注意要有空格,不然
1.4类的构造方法
在实例化对象时,对象的初始化是自动完成的 ,并且这个对象是空的。有时候,希望每一个对象都为初始化某些特征,这时就需要用到的构造方法。构造方法没有返回数据类型,其功能是在实例化类时完成一些初始化工作。
SAP 构造方法必须以METHODS CONSTRUCTOR定义,它将在每一次对象初始化时被自动调用。
damo
REPORT ZJGLTEST02.
CLASS CALLDEF DEFINITION.
PUBLIC SECTION. " 定义构造方法
METHODS CONSTRUCTOR.
PRIVATE SECTION.
DATA : OUTPARA TYPE STRING.
ENDCLASS.
CLASS CALLDEF IMPLEMENTATION. " 定义执行构造方法
METHOD CONSTRUCTOR.
OUTPARA = 'Execute SAP Construct'.
WRITE : OUTPARA.
ENDMETHOD.
ENDCLASS.
DATA:CALLDEF TYPE REF TO CALLDEF.
START-OF-SELECTION.
CREATE OBJECT CALLDEF. "初始化类实例对象时即调用构造函数.
1.4类的继承
1.4.1类继承的基本概念及应用
类继承的本质是代码重用。当要构造一个新类时,无需从零开始,可以参考一个已有的类,在其基础上建立一个新类,我们称参考类为“基类”或“父类”,新建类为“派生类”或“子类”。派生类可以继承基类所有的属性和方法,并可以在此基础上添加新有特性。
在类定义时,使用inheriting from 附加项可以指定派生类和基类之间的继承关系,一个类可以有多个派生类但只通用一个基类。
REPORT ZJGLTEST02.
* CLASS SUPERCLASS DEFINITION 建立一个基类 *
CLASS SUPERCLASS DEFINITION.
PUBLIC SECTION.
METHODS WRITE_FIRST.
METHODS WRITE_SECOND.
ENDCLASS.
* 建立派生类
CLASS SUBCLASS DEFINITION INHERITING FROM SUPERCLASS.
PUBLIC SECTION.
METHODS WRITE_THIRD.
ENDCLASS.
* 定义基类实现方法
CLASS SUPERCLASS IMPLEMENTATION.
METHOD WRITE_FIRST.
WRITE:/ 'The First method'.
ENDMETHOD.
METHOD WRITE_SECOND.
WRITE:/'The Second method'.
ENDMETHOD.
ENDCLASS.
* 定义派生类实现方法
Class SUBCLASS IMPLEMENTATION.
METHOD WRITE_third.
write:/'The Third Method'.
ENDMETHOD.
ENDCLASS.
DATA:INHER_OBJ TYPE REF TO SUBCLASS.
START-OF-SELECTION.
CREATE OBJECT INHER_OBJ.
CALL METHOD: INHER_OBJ->WRITE_FIRST,
INHER_OBJ->WRITE_SECOND,
INHER_OBJ->WRITE_THIRD.
1.4.2多态性类继承的实现
继承使基类的对象能够通过派生类实现,在实际应用中,但实际应用中,由于每个派生类的属性不同,
相同的基类对象在不同的派生类中需要以不同的方式来表现。在类的继承中提供多态的概念,可在派生类中定义肯基类相同的接口,但是可以使用不同的代码来实现,多态性也就意味着相同的用户操作在不同的类中有不同的实现形式。
定义类的多态性,需要在派生类方式中进行如下声明:
METHOD REDEFINITION.
所定义的方法名与基类中一致,不过实现过程不同。访问各派生类时,将采用用的派生类方法实现,原有的基类方法被屏蔽。若在派生类内部需要运用基类的方法,可以使用关键字super来指定。
CALL METHOD SUPER ->.
调用派生类中的重载方法可以通过方法名直接引用或通过运算符"ME->"来调用。
CALL METHOD ME->.
DAMO
REPORT zjgltest02.
CLASS superclass DEFINITION. " 定义基类
PUBLIC SECTION .
DATA : para(30) TYPE c VALUE 'The Super method'.
METHODS write_first.
ENDCLASS.
CLASS subclass DEFINITION INHERITING FROM superclass. " 定义派生类
PUBLIC SECTION.
METHODS write_first REDEFINITION. " 定义重置方法
METHODS write_second.
ENDCLASS.
CLASS superclass IMPLEMENTATION. " 定义基类实现方法
METHOD write_first.
WRITE: / para.
ENDMETHOD.
ENDCLASS.
CLASS subclass IMPLEMENTATION.
METHOD write_first.
CALL METHOD super->write_first. " 调用基娄方法
ENDMETHOD.
METHOD write_second.
para = 'The redefinition method'. " 调用本身类的方法
CALL METHOD me->write_first.
ENDMETHOD.
ENDCLASS.
DATA: inher_obj TYPE REF TO subclass.
START-OF-SELECTION.
CREATE OBJECT inher_obj.
CALL METHOD: inher_obj->write_first, " 调用派生类的重置方法
inher_obj->write_second.
上例实现了在继承类中基类方法的重载,并实现了在派生类重载方法中对基类方法的调用,在派生类中的操作可以直接影响基类的的对象。
1.4.3 抽象类和抽象方法
有时一个基类中包含多个派生类,而所有操作都是在派生类中实现,并不需要通过基类来定义对象实例,通常情况下可以将该基类定义为一个模板,将该声明为抽象类。
其定义如下:
1.抽象类:含有1个或多个方法的类称为抽象类。抽象类不能使用CREATE OBJECT 来创建实例对象,它仅包含没有具体实现的方法,其定义如下:
CLASS DEFINITION ABSTRACT.
…
ENDCLASS.
2.抽象方法:只包含方法定义,但没有具体实现方法,需要通过其子类来实现,其定义如下
METHODS ABSTRACT.
DAMO
REPORT zjgltest02.
CLASS superclass DEFINITION ABSTRACT. " 定义一个抽象类
PUBLIC SECTION.
DATA:para(30) TYPE c VALUE 'The super method.'.
METHODS write_first ABSTRACT. " 定义一个抽象方法
ENDCLASS.
CLASS subclass DEFINITION INHERITING FROM superclass.
PUBLIC SECTION.
METHODS write_first REDEFINITION. " 继承基类抽象方法
METHODS write_second. " 在派生类中自定义方法
ENDCLASS.
CLASS subclass IMPLEMENTATION.
METHOD write_first.
WRITE:para.
ENDMETHOD.
METHOD write_second.
WRITE:'The Second method'.
ENDMETHOD.
ENDCLASS.
DATA: inher_obj TYPE REF TO subclass.
START-OF-SELECTION.
CREATE OBJECT inher_obj.
CALL METHOD:inher_obj->WRITE_FIRST,
inher_obj->WRITE_SECOND.
1.4.4 最终类和最终方法
最终类和最终方法都是不可继承的,其主要意义是为了防止由于设计中多级别派生类造成的语法和语义的冲突。
最终类定义语法:
CLASS DEFINITION FINAL.
…
ENDCLASS.
最终方法定义语法:
METHODS FINAL.
二.接口
接口和抽象类非常相似,它定义了一些未实现的属性肯方法。所有继承它的类都继承这些成员,某种意义上,可以把接口理解为一个类的模板。
接口和抽象类的相似之昝表现在以下两方面。
1)两者都包含可以由子类继承的抽象成员;
2)两者都不需要方法实现,不能直接实例化。
两者的区别表现在以下几个方面。
1)抽象类除拥有抽象成员外,还可以拥有非抽象成员,而接口所有成员都是抽象的;
2)抽象成员可以是私有的,而接口成员一般都是公有的;
2)接口中不能含有构造方法,静态成员肯常量;
2.1 接口的定义
在程序中定义局域接口的语法格式如下:
INTERFACE.
DATA…
CLASS-DATA…
METHOD…
…
ENDINTERFACE
接口没有自己的实例,其方法的实现需要通过具体的类进行,一个接口可以被任意多个不同的类实现。在类的定义中,接口的实现只能出现在公有的部分,接口中的所有组件灰被添加为该类的公有成员,其语法如下:
CLASS DEFINITION.
PUBLIC SECTION.
…
INTERFACES:INT1,INT2.
…
ENDCLASS.
2.2 接口的引用
接口的应用变量的定义与对象引用相似,语法如下:
TYPES|DATA iref TYPE REF TO intf.
其中intf为全局或程序中已定义的接口,接口成员的引用通过运算符"->"实现,使用类访问接口肯方法的语法格式如下:
intf->attr.
CALL METHOD intf->meth.
对于接口中的静态成员,如果该成员为变量,则只能通过接品引用进行访问:
intf=>const.
对于其它静态接口成员,可以通过实现该接口的类本身或者类引用进行访问:
class =>intf~attr.
CALL METHOD class=>intf~meth.
在直接调用接口方法时,必须先参考接口对象建立一个内表,再循环读取类表对象输出。
2.3 Demo
REPORT zjgltest02.
*定义接口
INTERFACE output.
METHODS write.
ENDINTERFACE.
* 定义引用接口的类
CLASS superclass DEFINITION.
PUBLIC SECTION.
INTERFACES output.
ENDCLASS.
* 类中定义接口方法的实现
CLASS superclass IMPLEMENTATION.
METHOD output~write.
WRITE:'Hello SAP'.
ENDMETHOD.
ENDCLASS.
DATA: class_obj TYPE REF TO superclass,
intf_obj TYPE REF TO output, " 引用接口
intf_table TYPE TABLE OF REF TO output. " 引用接口创内表
START-OF-SELECTION.
CREATE OBJECT:class_obj. "创建类的实例
CALL METHOD:class_obj->output~write.
LOOP AT intf_table INTO intf_obj. " 读取内表实例对象直接输出接口方法
CALL METHOD intf_obj->write.
ENDLOOP.
三:事件
事件用于捕获某类对象状态的改变来触了事件的方法并进行处理。
3.1 事件的定义
1)事件可以在类或接口中进行声明。
EVENTS|CLASS-EVENTS EVT
EXPORTING…VALUE(PL)TYPE type | LIKE f [optional |default g]
…
value(pn) TYPE type | like f [optional |default g].
实例事件中包含一个隐含参数SENDER,该参数的类型为触发事件的类或接口对象使用。
2)一个实例事件可以被类中的任意方法触发,静态事件则可以被静态方法触发。
raise event evt exporting p1 = f1 …pn =fn
damo
REPORT zjgltest02.
CLASS C1 DEFINITION.
PUBLIC SECTION.
EVENTS e1 EXPORTING VALUE(P1) TYPE i .
METHODS m1.
data a1 type i value 7.
ENDCLASS.
CLASS C1 IMPLEMENTATION.
METHOD M1.
RAISE EVENT e1 EXPORTING p1 = a1.
ENDMETHOD.
ENDCLASS.
3.2 事件处理方法
事件需要通过触发其声明代码中所定义的方法才能处理相关事物,任何类都可以调用其他类中所定义的事件或调用自身所定义的事件,其语法如下:
METHODS|CLASS-METHODS
Meth for exent evt of cif importing … ei…
一个事件处理方法的接口中只能包含定义在事件evt中的形式参数,并需遵守事件中的参数属性设定,但事件处理方法不需要使用所有RAISE EVENT 中定义的参数。若希望使用隐含参数SENDER,则必须将其列入参数接口列表中。
要使事件处理方法能够对事件进行响应,必须 在进行为相关事件注册方法,语法如下:
SET HANDLER …HI… [FOR]…
事件类型共分4种:定义在类中的实例及静态事件,定义在接口中的实例及静态事件。
对于实例事件,在进行处理之前必须在注册语句中使用附件项FOR指定注册对象,包括:
1)指定一个单独的对象作为事件触发者。
SET HANDLER h1 … hn for ref.
2) 注册所有可以触发该事件的实例,包括没有被创建的实例。
SET HANDLER H1 … HN FOR ALL INSTANCES
3)注册静态事件,该注册自动应用于整个类。
set handler h1…hn
在程序执行到RAISE EVENT语句后,所有已注册的处理方法都将在下一个语句之前被处理。处理方法按照其在系统内部注册的顺序执行,为避免无线循环,目前事件处理最多的不可能超过64级嵌套。
设置从1循环到50.当长是10的公倍数时,触发事件输出当前值。
3.3 damo
REPORT zjgltest02.
CLASS ADDING DEFINITION.
PUBLIC SECTION.
CLASS-DATA NUM TYPE I . " 定义静态变量用于统计累加值
EVENTS:RETURN. " 定义事件
METHODS: ACCUMLATE.
ENDCLASS.
CLASS ADDING IMPLEMENTATION.
METHOD:ACCUMLATE.
DATA :RES TYPE I. " 判断累加值是否能整除10.若可以则触发事件执行
NUM = NUM + 1.
RES = NUM MOD 10 .
IF RES = 0.
RAISE EVENT RETURN.
ENDIF.
ENDMETHOD.
ENDCLASS.
CLASS HANDLER DEFINITION. "定义事件所执行方法
PUBLIC SECTION.
METHODS HANDLE_EXECUTE FOR EVENT RETURN OF ADDING.
ENDCLASS.
CLASS HANDLER IMPLEMENTATION. "定义事件所执行方法的执行过程
METHOD HANDLE_EXECUTE.
WRITE:/'The present number is : ', ADDING=>NUM.
ENDMETHOD.
ENDCLASS.
DATA : O_ADDING TYPE REF TO ADDING,
O_HANDLER TYPE REF TO HANDLER.
START-OF-SELECTION.
CREATE OBJECT :O_ADDING,O_HANDLER.
SET HANDLER O_HANDLER->HANDLE_EXECUTE FOR ALL INSTANCES. "创建事件处理表
DO 50 TIMES.
CALL METHOD O_ADDING->ACCUMLATE. "循环调用时间,满足条件时触发执行
ENDDO.
四 定义系统全局对象
用SE24可以创建全局对象
五 BADI
BADI用到的是SE18和SE19来实现对于功能的
SE18: 创建对象
SE19: 来创建方法