1 面向对象基础
不多赘述何为对象与类。简单回顾一下在面向对象特性。
- 封装 限定内部资源的可见性
- 多态 相同名称的方法在不同类中不同的体现
- 继承 派生类
REPORT z_simple_object.
CLASS application DEFINITION.
PUBLIC SECTION.
METHODS:show_text.
PRIVATE SECTION.
DATA text(100) TYPE c VALUE 'This is my first ABAP Object'.
ENDCLASS.
CLASS application IMPLEMENTATION.
METHOD show_text.
WRITE text.
ENDMETHOD.
ENDCLASS.
DATA ob_app TYPE REF TO application.
START-OF-SELECTION.
CREATE OBJECT ob_app.
CALL METHOD ob_app->show_text.
2 类和对象
ABAP中的类由程序内部的局域类和全局类,其作用范围不同。但ABAP中的全局类是通过ABAP工作台中的类创建工具Class Bulider开发的,保存在系统类库程序(Class pool)中,可供所有程序使用;而在程序内部定义的类则一般只应用于本程序,但二者的定义原则和格式是一致的。
1 程序中的类定义
(1)类声明及实现
ABAP使用CLASS/ENDCLASS语句进行类定义,且由声明部分和具体实现部分组成。类声明部分中包含类成员(Component,又称Member,具体包括类的属性,方法和事件等)的名称及说明。
CLASS class DEFINITION.
PUBLIC SECTION.
...
PROTECTED SECTION.
...
PRIVATE SECTION.
...
ENDCLASS.
CLASS class IMPLEMENTATION.
METHOD ... ENDMETHOD.
...
ENDCLASS.
(2)成员可见性
类的各个成员都必须在DEFINITION部分进行声明。在ABAP对象中,共有三种可见性:
- 公共部分(PUBLIC SECTION)中定义的类成员可以被所有对象使用,包括类方法及派生类中定义的方法。
- 受保护部分(PROTECTED SECTION) 中定义的类成员只能被类及其派生类中的方法使用,外部不可见。
- 私有部分(PRIVATE SECTION)中定义的类成员只能被本身的方法所使用。
(3)成员类型
ABAP类中可以定义三种不同类型的成员,分别是属性,方法和事件。根据生存期的不同,由实例成员和静态成员之分。
实例成员仅隶属于一个特定的类实例,即一个对象,而静态成员则属于整个类,是所有的类对象共享的内存区域。
- 属性
对于实例属性,使用DATA语句定义,语法与数据对象声明相同;对于静态属性,则使用CLASS-DATA语句进行定义。属性在类的声明部分进行定义。
CLASS vehicle DEFINITION.
PULIC SECTION.
CLASS-DATA class_name(10) TYPE c VALUE 'Vehicle'.
PROTECTED SECTION.
DATA speed TYPE i.
ENDCLASS.
对于公有组件,可以在属性定义语句中增加READ-ONLY关键字,则该属性不能被类外部读取但可被类的内部方法所修改。这种定义方法避免了每次读取类属性时都需要分配相应的读取方法,因为直接获得类属性要比通过类方法更为高效。
- 方法
实例方法只能访问该对象实例中的所有属性和事件,而静态方法则只能访问类的静态属性和事件。
类方法需要在类的声明和实现两部分进行定义,在类的声明部分说明方法的参数接口,在类的实现部分则通过ABAP代码完成具体的功能。方法的声明关键字为METHODS和CLASS-METHODS;实现部分代码在语句METHOD和ENDMETHOD之间定义。
方法声明语法如下
METHODS meth
IMPORTING ... i TYPE type ...
EXPORTING... i TYPE type ...
CHANGING ... i TYPE type ...
EXCEPTIONS ... i TYPE type ...
- Importing 用于定义输入参数
- Exporting 用于定义输出参数
- Changing 用于定义输入输出参数
- Exceptions 用于定义可能出现的异常
在方法实现部分,不需要重复定义这个接口
METHOD meth
...
<ABAP Statement>
...
ENDMETHOD.
REPORT z_simple_object.
CLASS vehicle DEFINITION.
PUBLIC SECTION.
CLASS-DATA class_name(10) TYPE c VALUE 'Vehicle'.
METHODS:accelerate,
show_speed.
PROTECTED SECTION.
DATA speed TYPE i.
ENDCLASS.
CLASS vehicle IMPLEMENTATION.
METHOD accelerate.
speed = speed + 1.
ENDMETHOD.
METHOD show_speed.
WRITE: / 'Speed:', speed.
ENDMETHOD.
ENDCLASS.
2 定义系统全局类
可以长期存储,维护供整个系统调用,并在系统间传输。该类型不包含事件块,子程序,屏幕等元素,也不包含共有数据部分,因为也不能分配事务代码。
(1)全局类定于
说明:
level(级别,包括静态属性Static Attr. 实例属性Instance Attr. 常量Constant)
Visibility(可见性,PUBLIC,PROTECTED,PRIVATE)
Attributes(属性),Methods(方法),Parameters(参数接口)
在树形结构中双击方法名称,可以添加该方法的代码
(4)使用全局类
REPORT z_global_class.
DATA: o_vehicle TYPE REF TO z_cl_vehicle,
count TYPE i.
START-OF-SELECTION.
CREATE OBJECT o_vehicle.
DO 5 TIMES.
CALL METHOD o_vehicle->accelerate.
ENDDO.
CALL METHOD o_vehicle->show_speed.
3 程序中的类实例
ABAP类定义之后,并没有实现任何功能,类似于数据类型定义,实际应用则必须通过类的实例-对象来实现。步骤如下:
1)定义类的声明与实现方法
2)使用DATA语句中的TYPE REF TO 选项参照类类型声明引用变量
3)使用CREATE OBJECT语句创建对象
4)通过"->"或"=>"运算符访问对象或类组件
(1)对象创建与引用
ABAP对象的创建和访问需要通过对象引用进行。在程序中,需要先根据对象类型声明引用类型变量,然后对该变量引用ABAP对象,该引用变量中实际存储的是ABAP对象的内存地址。
(2)访问对象组件
对象创建后,可以通过指向它的引用变量对其进行操作。可以使用的对象组件一般为当前可见的属性和方法,通过引用变量后接运算符“->”访问对象组件。oref->comp
其中,oref代表引用类型变量,comp代表要访问的类成员。“->”为对象选择运算符,可以用于访问类中定义的实例组件和静态组件。
对于类中的静态组件而言,还有另外一种访问方式,可以不通过实例和引用变量进行,而是通过类名称本身使用类成员选择运算符“=>”直接对类进行操作。class=>comp
REPORT z_simple_object.
CLASS vehicle DEFINITION.
PUBLIC SECTION.
CLASS-DATA class_name(10) TYPE c VALUE 'Vehicle'.
METHODS:accelerate,
show_speed.
PROTECTED SECTION.
DATA speed TYPE i VALUE 1.
ENDCLASS.
CLASS vehicle IMPLEMENTATION.
METHOD accelerate.
speed = speed + 1.
ENDMETHOD.
METHOD show_speed.
WRITE: / 'Speed:', speed.
ENDMETHOD.
ENDCLASS.
DATA o_vehicle TYPE REF TO vehicle.
START-OF-SELECTION.
WRITE vehicle=>class_name.
CREATE OBJECT o_vehicle.
CALL METHOD o_vehicle->accelerate.
CALL METHOD o_vehicle->show_speed.
由于引用类型变量本身也可以被定义为类属性,因而可以出现下述的链式访问结构
oref1->oref2->comp
或者class=>oref->comp
上述的两种运算符提供类的外部访问,在某些情况下,对象本身需要知道自身的地址,可以使用局部引用变量ME,该变量隐式的存在与所有的实例方法中,当方法被调用时,该变量将包含自身的地址指针,这种用法称为对象的自身引用。
访问内容 | 语法格式 |
---|---|
一个对象的实例属性或静态属性 | orer->attr |
类的静态属性 | class=>attr |
在类内部访问自身实例属性或静态属性 | me->attr 或 attr |
对象的实例属性或静态方法 | CALL METHOD orer -> meth |
类的静态方法 | CALL METHOD class=>meth |
在类内部访问自身实例方法或静态方法 | CALL METHOD me->attr 或 CALL METHOD attr |
(3)删除对象
对象占据程序内存,如果后续程序不再使用的对象,应该将其删除。系统对对象的删除操作与引用变量有关,系统将自动定时检测,如果一个对象不再被热任何变量引用,则将其删除,并释放其所占用的内存,这个操作就是通过垃圾回收机制完成。
垃圾收集器定时清除不再使用的对象,包括使用链式引用的对象,也可以被其检测删除。要让其发挥作用,只需简单的使用CLEAR语句初始化所有指向该对象的引用变量或者将引用变量的值改变。
REPORT z_simple_object.
CLASS vehicle DEFINITION.
PUBLIC SECTION.
CLASS-DATA class_name(10) TYPE c VALUE 'Vehicle'.
METHODS:accelerate,
show_speed.
PROTECTED SECTION.
DATA speed TYPE i VALUE 1.
ENDCLASS.
CLASS vehicle IMPLEMENTATION.
METHOD accelerate.
speed = speed + 1.
ENDMETHOD.
METHOD show_speed.
WRITE: / 'Speed:', speed.
ENDMETHOD.
ENDCLASS.
DATA: o_vehicle1 TYPE REF TO vehicle,
o_vehicle2 LIKE o_vehicle1.
START-OF-SELECTION.
CREATE OBJECT: o_vehicle1, o_vehicle2.
o_vehicle1 = o_vehicle2.
CLEAR o_vehicle2.
该程序中,当o_vehicle1指向新对象后,先创建的对象将被清除,而程序初始化变量o_vehicle2后,由于o_vehicle1仍指向第二个对象,所以该对象依然处于活动状态。
3 方法
1 参数的定义和传递
类方法的参数接口部分是在类声明部分通过METHODS语句定义的,而且该接口不需要在类的实现部分再次出现,参数接口的语法如下:
METHODS meth
IMPORTING ... [VALUE(Ii) | Ii] TYPE type [OPTIONAL|DEFAULT defi] ...
EXPORTING ... [VALUE(Ii) | Ii] TYPE type [OPTIONAL|DEFAULT defi] ...
CHANGING ... [VALUE(Ii) | Ii] TYPE type [OPTIONAL|DEFAULT defi] ...
RETURNING VALUE(r)
EXCEPTIONS ... Xi ...
- IMPORTING 指定一或多个输入参数
- EXPORTING 指定一或多个输出参数
- CHANGING 指定一或多个输入输出参数
- VALUE 指定参数传递形式,VALUE则为值传递,也可使用VALUE中的REFERENCE附加项显示指定引用传递
- TYPE 指定参数传递形式,也可使用LIKE参照已经定义好的数据对象类型
- OPTIONAL和DEFAULR 通常情况下,已定义的输入参数必须在调用时进行传递,除非使用OPTIONAL选项指定该参数为可选的,此时程序将使用该参数类型的初始值进行传递,或者是使用DEFAULT选项后指定的默认值。
- RETURNING 该选项可以替代IMPORTING和EXPORTING
2 调用方法
在调用方法时,除去指定为可选参数之外,所有的参数都必须传递相应的实参值。语法结构如下:
CALL METHOD [oref->|class=>] meth
EXPORTING ... Ii = Fi ...
IMPORTING ... Ei = Gi ...
CHANGING ... Ci = Ci ...
RECEIVING r = h
EXCEPTIONS ... Xi = RCi ...
该语句格式适用于包括类内部直接调用(不需要操作符),实例调用(oref->)和静态调用(class=>)三种情况。其中参数定义时用IMPORTING选项指定的形参i此时将接受CALL METHOD语句中的EXPORTING中传递的实参f;而用EXPORTING指定的形参e此时将通过IMPORTING选项传递给实参g。
方法内部的意外处理与功能模块相似,异常通过RAISE和MESSAGE RAISE语句触发,并通过系统字段SY-SUBRC返回相关错误代码。
REPORT z_method_para.
CLASS vehicle DEFINITION.
PUBLIC SECTION.
METHODS: accelerate IMPORTING rate TYPE i,
show_speed.
PRIVATE SECTION.
DATA speed TYPE i VALUE 0.
ENDCLASS.
CLASS vehicle IMPLEMENTATION.
METHOD accelerate.
speed = speed + rate.
ENDMETHOD.
METHOD show_speed.
WRITE: / 'Speed:', speed.
ENDMETHOD.
ENDCLASS.
DATA o_vehicle TYPE REF TO vehicle.
START-OF-SELECTION.
CREATE OBJECT o_vehicle.
CALL METHOD o_vehicle->accelerate EXPORTING rate = 2.
CALL METHOD o_vehicle->accelerate EXPORTING rate = 2.
CALL METHOD o_vehicle->show_speed.
ABAP Objects还提供另一种形式
CALL METHOD [oref->|class=>] meth
PARAMETER-TABLE ptab.
EXCEPTION-TABLE etab.
其中实参必须在程序中放置在两个特定类型的内表中,传递给方法。其中参数表ptab可以参照类型组ABAP中的ABAP_PARMBIND(行类型)和ABAP_PARMBIND_TAB(表类型)生成;异常表etab可以参照ABAP_EXCBIND(行类型)和ABAP_EXCBIND_TAB(表类型)生成。
3 函数方法
函数也是一种过程模块其特殊之处是在调用时可以使用操作符(如“=”)来替代过程调用语句,并可作为操作数直接应用于操作语句中。
METHODS meth
IMPORTING ... [VALUE(Ii)|Ii] TYPE type [OPTIONAL|DEFAULT def] ...
RETURNING VALUE(r).
一个函数方法可以拥有任意数量的输入参数,但只有一个输出参数,且输出参数必须为值传递而且需要完全限定其类型。
CALL METHOD [oref->|class=>] meth
EXPORTING ... Ii = Fi ...
RECEIVING r = h.
REPORT z_functional_method.
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.
*
PARAMETERS radius TYPE i.
DATA: o_circle TYPE REF TO circle,
area TYPE f.
START-OF-SELECTION.
CREATE OBJECT o_circle.
CALL METHOD o_circle->get_area
EXPORTING
i_radius = radius
RECEIVING
r_size = area.
WRITE: / area.
area = o_circle->get_area( radius ).
WRITE: / area.
4 构造方法
构造方法是由运行时环境自动调用的一种方法,用于为对象设定一个初始状态。构造方法也存在静态和实例两种形式。构造方法并不一定需要在类中定义,系统通常会自行生成一个默认的构造方法,将对象状态设置为初始值。
实例构造方法在每一次对象创建的过程中(即使用CREATE OBJCT语句时)被系统调用,如果在类声明部分进行声明,则需要在实现部分进行代码实现。该方法与一般方法有两点区别:一是有预定义名称CONSTRUCTOR;二是该方法必须在共有部分进行声明。
METHODS constructor
IMPORTING ... [VALUE(Ii)|Ii] TYPE type [OPTIONAL|DEFAULT def] ...
EXCEPTIONS ... e ...
构造方法中不包含任何形式的输出参数,其功能只是定义对象状态,而不是对其进行改变。构造方法在CREATE OBJECT语句中被调用,因此根据实例构造方法的定义,该语句本身也可以包含输出参数EXPORTING和返回值EXCEPTION选项。如果在对象创建过程中出现异常,则对象被删除,引用变量设为初始值。
REPORT z_method_constructor.
CLASS vehicle DEFINITION.
PUBLIC SECTION.
METHODS: accelerate IMPORTING rate TYPE i,
constructor IMPORTING i_speed TYPE i,
show_speed.
PRIVATE SECTION.
DATA speed TYPE i VALUE 0.
ENDCLASS.
CLASS vehicle IMPLEMENTATION.
METHOD accelerate.
speed = speed + rate.
ENDMETHOD.
METHOD show_speed.
WRITE speed.
ENDMETHOD.
METHOD constructor.
speed = i_speed.
ENDMETHOD.
ENDCLASS.
DATA o_vehicle TYPE REF TO vehicle.
START-OF-SELECTION.
CREATE OBJECT o_vehicle EXPORTING i_speed = 4.
CALL METHOD o_vehicle->accelerate EXPORTING rate = 2.
CALL METHOD o_vehicle->accelerate EXPORTING rate = 2.
CALL METHOD o_vehicle->show_speed.