
ABAP 类
一、介绍
类(Class)可看做是对象的骨骼(Template)或者对象的类型。另外,类是抽象化对象的明细表。即可以说是制作对象的设计书。对象属性由描述对象的状态和行为的构成要素(Component)决定。
二、 全局/本地类
ABAP对象中可以定义全局(Global)类、本地(Local)类。在ABAP工作区中利用事务码 T-CODE:SE24(类编辑器)定义全局类与全局接口。如此定义的类存储在类池(ClassLibrary in the Repository)中,且所有的 ABAP 程序都可对其进行访问。局部类与局部接口只能在程序内部定义,且只有该程序才能使用。系统首先会寻找程序内部定义的局部类,其不存在时才去寻找全局类。在 ABAP程序内使用时,全局类与局部类没有明显差别。
下面了解关于在程序内部定义类和实现方法的语句。
DEFINITION:定义类的构成项目(属性、方法、事件)。
CLASS class DEFINITION.
ENDCLASS.
IMPLEMENTATION:实现类的方法。
接下来创建一个简单的 ABAP面向对象程序,先定义一个类,然后调用此类的一个程序。 [例14-3]
REPORT z14_03.
CLASS c1 DEFINITION.
PUBLIC SECTION
METHODS meth.
ENDCLASS. "CI DEFINITION
CLASS C1 IMPLEMENTATION
METHOD meth.
WRITE /'CLASS TEST
ENDMETHOD.
ENDCLASS. "CI IMPLEMENTATION
DATA : go_crefTYPE REF TO cl
START-OF-SELECTION.
CREATE OBJECT go_cref.
CALLMETHOD go_cref->meth.
[结果14-3]
CLASS TEST
[例 14-3]显示了在程序中定义类(c1)后,编写方法进行调用的情况。
三、Class构成要素
类的所有要素在声明部分(Declarationpart)实现。构成要素在类中定义对象属性。定义类时,各个项目需定义在三个访问区域(VisibilitySection)之一。访问区域定义类之间的外部接口(Interface)。类的所有项目在类中均可视,但根据声明方式不同,有的项目无法在其他类中使用。类的所有项目在同一个Namespace中,这意味着类的各个项目都有唯一的名字。
类中存在两种构成要素。一种是各个类的对象中都存在的,另一种与实例数无关,整个类就存在一个。前者是实例-specific项目,叫做实例Component(实例组件)。该项目是参照类创建对象时,内存中存在的项目,每每创建对象时都会被初始化。后者是on实例-specific 项目,也叫作静态组件。该项目从遇到创建类的语句(CREATEOBJECT语)开始,直到程序结束都存储于内存中,是依赖类存在的项目。Static属性用CLASS-DATA语句声明,Static方法用CLASS-METHOD方法声明。
Static属性和方法是为了制作类组件而声明的,即使不创建对象,若已存在于内存中即可以直接使用。在 ABAP 对象中,类可以定义以下项目(Attribute、Method、Event)。
1.属性(Attribute)
属性(Attribute)可以拥有 ABAP 所有数据类型的类内部数据字段。对象状态由属性的内容决定。属性的一种类型是Reference Variable。Reference Variable 可以创建对象及指定地址。Reference Variable可在类内部定义,并且使它从类内部访问对象。具体内容在143节里详细讲述。
实例属性的组件定义Instance-specific 对象的状态。
在类中可使用DATA语句声明此类属性。
DATA ldata TYPE c.
静态属性组件是指定义类的所有实例都可以使用的类状态。即与实例个数无关,依赖类存在,且是类固有的区域。
利用CLASS-DATA语句声明。在类实际环境中可以访问。此两种类型的定义方法可参见[表 14-1]。
CLASS-DATA cdata TYPE i.
2.方法(Method)
方法用来定义决定对象行为的类内部执行步骤。方法可以访问类的所有属性,且可通过方法修改对象内容。另外,还提供传入传出参数,便于用户交互。在这方面类似于Fumction Module。类的PRIVATE属性只能通过同一类的方法进行修改。在类声明(DEFINTION)部分,利用 METHOD语句定义,在IMPLEMNT部分记载方法的功能。
METHOD meth.
...
ENDMETHOD.
Instance Method:利用METHODS语句声明实例方法。该方法在类的所有属性中均可访问,且类的所有事件均可调用它。 下面做一个关于类的程序,在类中声明两个方法,分别是传入/传出值方法。 [例14-4]
REPORT z14_04.
CLASS cI DEFINITION.
PUBLIC SECTION.
DATA :l_char TYPE char20.
METHODS : set_data IMPORTING p_imp TYPE char20,
get_data EXPORTING p_exp type char20.
ENDCLASS. "c1 DEFINITION
CLASS C1 IMPLEMENTATION.
METHOD set_data.
l_char=p_imp.
ENDMETHOD.
METHOD GET_data.
P_exp=L_CHAR
ENDMETHOD.
ENDCLASS. "c1 IMPLEMENTATION
DATA: go_cref TYPE REF TO c1.
DATA:gv_data type char20.
START-OF-SELECTION.
CREATE OBJECT go_cref.
CALL METHOD: go_cref->set_data
EXPORTING p_imp= 'Test Class Method'
CALL METHOD: go_cref->GET_data
IMPORTING p_exp= gv_data
WRITE gv_data.
3.事件(Event)
事件是没有继承关系的类之间可以相互调用彼此方法的特殊方法。对象(或者类)为了调用其他对象(或者类)的事件控制方法时需要使用事件(事件控制方法也是一种方法。)如[例 14-4]练习所示,通过CALL METHOD 语句调用一般方法时,一个方法可以被多个对象调用。同理,所有对象都可调用事件,且只有事件的主人才能执行事件。调用一般方法时,调用方法的程序可以决定方法。同理,在事件中可决定 Handler 要反映的事件。在相同类中。类事件在使用RAISEEVENT语句的方法中调用。而调用其他类的事件时,利用FOREVENT evt OF class 语句。 [事件声明]
EVENTS eVt EXPORTING.. VALUE(el e2 .) TYPE type [OPTIONA]...
[调用事件(trigger)]
RAISE EVENTeVt EXPORTING el =fl e2 = f2 ...
[Event Handler Method 声明]
METHODS meth FOR EVENT evt OF cifIMPORTING el e2 ...
[Event Handler Method 登录]
SET HANDLER hl h2 ... [FOR]....
4.访问权限区域(Visibility Section)
如[图 14-5]所示,类访问权限领域共分为三种(在JAVA语言中PUBLIC
、PROTECTED
、PRIVATE
也称为访问权限)。类的所有构成要素都需声明在访问权限以内。
- PUBLIC SECTION
在PUBLICSECTION访问权限下定义项目,则在所有类中都可以访问。PUBLIC 类的组件(=成员,项目)构成类与用户之间的接口。 - PROTECTED SECTION
在PROTECTED访问权限下定义的项目,只有自己和继承类才能访问,且充当继承类之间的接口。 - PRIVATE SECTION 在PRIVATE访问权限下定义的项目,只显示在相同类的方法中。在外部区域中无法访问,封装在内部类中。IMPLEMENTATION部分的所有方法在类中都可以访问,没有任何限制。
封装(Encapsulation)
封装的基本目的是只能通过对象内部函数使用及修改对象内部数据,对外不公开内部结构。隐藏内部结构能简化对象,即使不清楚内部结构也可以方便使用。
通过[例 14-5]观察访问权限在程序中的使用方法。 [例14-5]
REPORT Z14_05.
CLASS CI DEFINITION.
PUBLIC SECTION.
METHODS : set_data IMPORTING p_imp TYPE i,
get_data EXPORTING p_exp TYPE i.
* PROTECTED SECTION.
DATA :l_num TYPE i.
ENDCLASS. "c1 DEFINITION
CLASS c1 IMPLEMENTATION,
METHOD set_data.
lnum =p_imp.
ENDMETHOD.
METHOD get_data.
pexp=lnum + 1.
ENDMETHOD.
ENDCLASS. "cI IMPLEMENTATION
DATA: go_cref TYPE REF TO c1.
DATA: gv_data TYPE i.
START-OF-SELECTION.
CREATE OBJECT go_cref.
CALL METHOD: go_cref->set_data
EXPORTING p_imp='10'.
WRITE : 'set_data Method :', go_cref->l_num.
CALL METHOD: go_cref->get_data
IMPORTING pexp=gv_data.
WRITE : /'get_data Method :', gv_data.
[结果 14-5]
set_data Method: 10
get_data Method: 11
[例14-5]是将类中变量1num加1后的值取出来,显示到画面的程序。若解除程序中的 PROTECTED SECTION 行的注释,在调用方法的go_cref->set_data 行中会出现如[图14-6]所示的错误。 即若使用 PROTECTED SECTION,则需参照继承类创建对象。
利用[例14-6]中的类定义继承关系,有继承关系的类之间的PROTECTED、PRIVATE属性可通过下面的实例进行学习。
378 [例14-6]
REPORT z14_06.
CLASS c1 DEFINITION.
PROTECTED SECTION
DATA : l_num TYPE i.
ENDCLASS. "CI DEFINITION
CLASS c2 DEFINITION INHERITING FROM c1.
PUBLIC SECTION.
METHODS : set_data IMPORTING p imp TYPE i.
get_data EXPORTING p_exp TYPE i.
ENDCLASS.
CLASS c2 IMPLEMENTATION.
METHOD set_data.
lnum=p imp.
ENDMETHOD.
METHOD get_data.
pexp=lnum +l.
ENDMETHOD.
ENDCLASS. "c1 IMPLEMENTATION
DATA: go_cref TYPE REF TO c2
DATA: gv_data TYPE i.
START-OF-SELECTION.
CREATE OBJECT go_cref.
CALL METHOD: go_cref->set_data
EXPORTING pimp = '10'.
CALL METHOD:go_cref->get_data
IMPORTING pexp=gv_data.
WRITE : /'get_data Method :', gv_data.
[结果14-6]
GET DATA Method : 11
[例 14-6]中的PUBLIC语句修改成PROTECTED后,C类继承c2类后执行程序。通过程序可确认,在继承类中也可以访问父类中的PROTECTED成员。然后重新将PROTECTED修改为 PRIVATE,会出现如[图 14-7]所示的错误信息,即继承类是无法访问父类的 PRIVATE 成员。