ABAP基础语法篇(8)——模块化
8.1 宏的定义和调用
要定义包含部分源代码的宏, 使用 DEFINE
语句,用法如下:
DEFINE <macro>.
<statements>
END-OF-DEFINITION.
这就定义了宏 <macro>
。必须在 DEFINE
和 END-OF-DEFINITION
之间指定完整的语句。这些语句最多可以包含九个占位符( &1 , &2 ,…, &9 )。
完成宏定义 之后,就可以 进行调用,方法如下:
<macro> [<p1><p2> ... <p9>].
在生成程序期间,系统用已定义的语句替换 <macro>
,用 <pi>
替换每个占位符 &i
。可以从宏中调用另一个宏,但宏不能调用自己。
8.2 使用包含程序
要从另一个 ABAP/4 程序中调用包含程序,使用 INCLUDE
语句,用法如下:
INCLUDE <incl>.
在语法检查期间和生成期间,该语句将源代码 <incl>
插入到 ABAP/4 程序中。 INCLUDE
语句的功能类似于把 <incl>
源代码复制到调用程序中语句的位置上。
INCLUDE
语句必须单独占一行,并且不能扩展到多行。
包含程序不是运行时装载的,而是在程序生成前就被解析。程序生成后,则包含所用全部包含程序的源代码。
8.3 调用子程序*
8.3.1 调用内部子程序
要调用内部子程序, 使用 PERFORM
语句,用法如下:
PERFORM <subr> [<pass>].
调用子程序 <subr>
。在 <pass>
选项中,指定如何与子程序进行数据传递。如果不使用 <pass>
选项,子程序也可以访问主 ABAP/4程序中声明的所有数据类型和对象。该数据叫做全局数据,如果不被同名局域数据隐藏,该数据对子程序可见。
8.3.2 调用外部子程序
要调用外部子程序, 使用 PERFORM
语句,用法如下:
PERFORM <subr>(<prog>) [<pass>] [IF FOUND].
调用程序 <prog>
中定义的子程序 <subr>
。如果希望与子程序进行数据传递,必须定义 <pass>
选项或者使用公用部分。如果使用 IF FOUND
选项,并且程序 <prog>
中没有子程序 <sub>
,系统就忽略 PERFORM
语句。
启动调用外部子程序的程序时,如果定义了子程序的程序不在内存中, ABAP/4
就将其装载到内存中。为了节省存储空间,尽量将不同程序中定义的子程序数目限制到最小。
8.3.3 运行时指定子程序名
运行时,可以指定要调用的子程序名以及存储子程序的程序名。为此使用 PERFORM
语句,用法如下:
PERFORM (<fsubr>) [IN PROGRAM (<fprog>)] [<pass>] [IF FOUND].
系统执行字段 <fsubr>
中存储的子程序。如果使用 IN PROGRAM
选项,系统在字段 <fprog>
中存储的程序内查找子程序(外部调用)。否则,系统在当前程序中查找子程序(内部调用)。
使用该语句还可在程序代码中指定子程序名和外部程序名。为此请忽略括弧。 <pass>
选项指定如何与子程序进行数据传递。如果使用 IF FOUND
选项,找不到子程序 <sub>
时,系统就忽略 PERFORM
语句。
8.3.4 从列表中调用子程序
要从列表中调用特定子程序, 使用 PERFORM
语句,用法如下:
PERFORM <idx> OF <form1><form2> ....<formn>.
系统执行子程序列表中位于 <idx>
处的子程序。 PERFORM
语句的这一变量只对内部调用有效。字段 <idx>
既可以是变量也可以是文字。
8.4 通过参数进行数据传递
可以用参数在调用程序和子程序之间进行数据传递。
在定义子程序期间用 FORM
语句定义的参数叫做形式参数。
在调用子程序期间用 PERFORM
语句指定的参数叫做实际参数。
可以区分不同种类的参数:输入参数用于向子程序传递参数 ;输出参数用于从子程序传递参数 ; 输入 / 输出参数用于与子程序进行参数传递
在 FORM
和 PERFORM
语句的
FORM <subr> [TABLES <formal table list>]
[USING <formal input list>]
[CHANGING <formal output list>]....
PERFORM <subr>[(<prog>)] [TABLES <actual table list>]
[USING <actual input list>]
[CHANGING <actual output list>]....
选项 TABLES
、 USING
和 CHANGING
必须按上述顺序编写。
列表中 USING
和 CHANGING
后面的参数可以是所有类型的数据对象和字段符号 。列表中 TABLES
后面的参数既可以是有表头行的内表,也可以是不带表头行的内表。可以采用 TABLES
、 USING
或 CHANGING
传送内表。
对于 FORM
语句中 USING
和 CHANGING
后面列表中的每个形式参数,可以指定不同数据传递方式:
通过参考值调用:
在子程序调用期间,仅将实参数的地址传送给形式参数。形式参数本身没有内存。在子程序中使用调用程序的字段。更改形式参数之后,调用程序中的字段内容也会变动。
通过值调用:
在子程序调用期间,形式参数是作为实参数的副本创建的。形式参数有自己的内存。更改形式参数并不影响实参数。
通过值和结果调用:
在子程序调用期间,形式参数是作为实参数的副本创建的。形式参数有自己的内存空间。在子程序末尾,将对形式参数的更改复制给实参数。
8.4.1 通过参考传递
要通过参考值在调用程序和子程序之间进行数据传递, 使用 FORM
和 PERFORM
语句 <pass>
选项的 USING
或 CHANGING
,用法如下:
FORM ..... [USING <fi1> ... <fin>] [CHANGING <fo1> ... <fon>] ...
PERFORM... [USING <ai1> ... <ain>] [CHANGING <ao1> ... <aon>] ...
在 USING
和 CHANGING
后面的列表中指定形式参数和实参数,而不需附加任何内容。
FORM
语句中形式参数的名称可以与 PERFORM
语句中实参数 <ai1> ... <ain> and <ao1> ... <aon>
的名称不同。 PERFORM
语句列表中的第一个参数传递给 FORM
语句相应列表中的第一个参数,以此类推。
对于通过参考值调用, USING
和 CHANGING
完全相同。对于文档, USING
用于子程序中的固定输入参数,而 CHANGING
则用于子程序中变化的输出参数。
8.4.2 通过值传递
要确保输入参数在调用程序中保持不变(即使子程序中已被更改),可以通过值将数据传递给子程序。
为此, 使用 FORM
和 PERFORM
语句 <pass>
选项的 USING
,用法如下:
FORM ..... USING ...VALUE(<fii>) ..
PERFORM... USING .......<aii> ..
通过对 FORM
语句中 USING
后面列表中的形式输入参数写入 VALUE(<fii>)
而不是 <fii>
,相应参数就通过值进行传递。与实字段 <ai>
属性相同的 PERFORM
语句调用该子程序时,就会创建一个新的局域字段 <fi>
。系统处理独立于调用程序中参考字段的该字段。
8.4.3 通过值和结果进行传递
如果仅希望在子程序运行成功之后,才将更改过的输出参数从子程序返回给调用程序,
使用 FORM
和 PERFORM
语句 <pass>
选项的 CHANGING
,用法如下:
FORM ..... CHANGING ...VALUE(<fii>) ..
PERFORM... CHANGING .......<aii> ..
通过对 FORM
语句中 CHANGING
后面列表中的形式输入参数写入 VALUE(<fii>)
而不是 <fii>
,相应参数通过值和结果调用进行传递。与实字段 <ai>
属性相同的 PERFORM
语句调用该子程序时,就会创建一个新的局域字段 <fi>
。系统处理独立于调用程序中参考字段的字段。
仅在运行到 ENDFORM
语句时,系统才将 <fii>
的当前值传递给 <aii>
。如果子程序因为某个对话信息而中断,则实参数 <aii>
保持不变。
8.5 在子程序中定义局部数据类型和对象
8.5.1 定义动态局部数据类型和对象
可以用 TYPES
和 DATA
语句,按照创建数据对象和数据类型中的说明,在子程序内创建局部数据类型和数据对象。为每个子程序调用新近定义的这些类型和对象将在退出子程序时删除。
每个子程序均有自己的局域命名空间。如果用与全局数据类型或对象相同的名称定义局部数据类型或对象,则不能在子程序中访问全局数据类型或对象。局部数据类型或数据对象会隐藏同名全局数据类型或对象。这意味着,如果在子程序中使用某个数据类型或对象名,则总是定址局部声明的对象(如果存在),否则,定址全局声明的对象。
8.5.2 定义静态局部数据类型和对象
如果想在退出子程序后保留局部数据对象之值,必须使用 STATICS
语句而非 DATA
语句进行声明。使用 STATICS
声明已全局定义,但仅在定义它的子程序中局部可见的数据对象。
8.5.3 显示定义全局数据对象
要避免全局数据对象值在子程序内被更改, 使用 LOCAL
语句,用法如下:
LOCAL <f>.
只能在 FORM
语句和 ENDFORM
语句之间使用该语句。对于 LOCAL
,可以保存无法被子程序内的数据声明隐藏的全局数据对象值。
8.6 调用Function功能模块
要从 ABAP/4 程序调用功 能模块, 使用 CALL
语句,用法如下:
CALL FUNCTION <module>
[EXPORTING f1 = a1 .... fn = an]
[IMPORTING f1 = a1 .... fn = an]
[CHANGING f1 = a1 .... fn = an]
[TABLES f1 = a1 .... fn = an]
[EXCEPTIONS e1 = r1 .... en = rn [OTHERS = ro]].
可以将功能模块 <module>
的名称指定为文字或变量。通过将实参数显式指定给EXPORTING
、 IMPORTING
、 TABLES
或 CHANGING
选项后面列表中的形式参数,与功能模块之间进行参数传递。
分配总是有以下格式: <formal parameter> = <actual parameter>
(1) EXPORTING
选项允许将实参数 ai
传递给形式输入参数 fi
。在功能模块中,必须将形式参数声明为输入参数。
(2) IMPORTING
选项允许将形式输出参数 fi
传递给实参数 ai
。在功能模块中,必须将形式参数声明为输出参数。
(3) CHANGING
选项允许将实参数 ai
传递给形式参数 fi
,并在处理功能模块后,系统将(更改过的)形式参数 fi
传递回实参数 ai
。在功能模块中,必须将形式参数声明为更改参数。
(4) TABLES
选项允许在实参数和形式参数间传递表格。借助该选项,内表总是通过参考值传递。
EXPORTING
、 IMPORTING
和 CHANGING
选项的参数可以是任意类型的数据对象。
这些选项的功能类似于子程序的 FORM
和 PERFORM
语句中的 USING
和 CHANGING
选项。TABLES
选项的参数必须为内表。 TABLES
选项对应于 FORM
和 PERFORM
语句的 TABLES
选项。
用 EXCEPTIONS
选项,可以处理功能模块处理过程中发生的例外。
例外是功能模块的特殊参数。有关如何定义和出现例外的内容,创建和编程功能模块中有专门说明。
如果出现 ei
例外,则系统停止执行功能模块,并且不将任何值从功能模块传递给程序,通过参考值传递的值例外。
如果在 EXCEPTION
选项中指定了 ei
,则调用程序通过将 ri
分配给 SY-SUBRC
来处理例外。必须将 ri
指定为数字文字。可以使 EXCEPTION
列表中的 OTHERS
处理列表中没有显式指定的所有例外,并且可将同一数值 ri
用于多个例外。