本节将结合实例介绍Data Reference和 Field Symbols的关系。
Field Symbols
SAP给出的Field Symbol的标准定义为:“Field Symbol是其他字段的‘占位符’或者是符号名。并不给字段分配实际的物理空间,但是指向该字段的内容。字段符号能指向任意的数据对象。只有在程序中被声明之后,Field Symbol指向的数据对象才被分配。”
Field Symbol没有地址,但是它将指向数据对象的地址;或者是指向它所分配的数据对象的内容。
我们在执行Modify和Append操作时,FieldSymbol的性能是比较优越的。因为数据更新操作不适用额外的内存空间。相比Worl Area ,FieldSymbol 的性能更加优越。
注意:Field Symbol在没有指定数据对象之前,是不能使用的。这意味着,在使用之前,必须指定变量(Variable)或者结构体(Structure)或者内表(Internal table)。记住这条规则,将使使用过程更加容易。
1、数据变量的FieldSymbol
DATA:nol TYPE i VALUE 10.
FIELD-SYMBOLS: <fs> TYPE i.
ASSIGN nol TO <fs>.
<fs> = 20.
WRITE: / <fs>.
结果输出的是25.
2、结构体的FieldSymbol
DATA: wa_sflight TYPE sflight.
FIELD-SYMBOLS: <fs_sflight> TYPE sflight.
ASSIGN wa_sflight TO <fs_sflight>.
SELECT SINGLE * FROM sflight INTO wa_sflight.
IF sy-subrc EQ 0.
<fs_sflight>-carrid = 123.
<fs_sflight>-connid = 456.
ENDIF.
WRITE:/
wa_sflight-carrid,
wa_sflight-connid.
结果输出是:123 0456
3、内表的Field Symbol
DATA: it_sflight TYPE TABLE OF sflight.
FIELD-SYMBOLS: <fs_sflight> TYPE sflight.
SELECT *
FROM sflight
INTO TABLE it_sflight
WHERE carrid = 'AA'.
LOOP AT it_sflight ASSIGNING <fs_sflight>.
WRITE:/
<fs_sflight>-connid,
<fs_sflight>-carrid.
ENDLOOP.
当使用loop通过ASSIGNING <fs_sflight>指定Field Symbol时,对<fs_sflight>操作就是对分配到字段上的内容进行操作。工作原理类似于“引用值传递”。在FS上进行的操作,和直接在内表记录上的操作是一样的效果。
FS可能的语法结构包括:
READ TABLE <itab> assigning <fs>....
LOOP AT <itab> assigning <fs>....
ASSIGN <data object> TO <fs>...
ASSIGN COMPONENT <component name/component index> TO <FS>...
APPEND INITIAL LINE TO <itab> ASSIGNING <fs>....
DATAREFERENCES
首先引出几个问题:
Q:什么是对象/类应用?当我们给类的变量创建引用时,会发生什么?
ANS:对象是类的实例。当我们创建一个类的实例时,类的内容将会被分配内存空间,指定相应的值。
Q:什么是数据引用?
ANS:数据的实例化叫做“DataReference”。简单来说,当我们想在运行环境中创建数据对象时,将会分配相应的内存或者数据。
那么,我们什么时候使用“Data Reference”?
当我们不能确定要创建何种类型的数据对象是,我们才会考虑数据引用。
DR的类型包括:
1、已知的数据引用:我们清楚的知道我们需要在运行环境中创建何种数据类型时。
2、未知的数据引用:以此类推。
注意:???
It we know data type, then it doesn’t make sense to
create data reference. But before understanding Unknown datareferences, it is
must to understand Know creation of Data reference for knowndata types.
Data Reference的语法:
创建整型(Integer)数据:
DATA lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE i.
*(or)
DATA:lv_data TYPE REF TO i.
CREATE DATA lv_data.
以上两种语法都是通用的,推荐使用前者。
在讨论以上两种类型之前,首先讨论一个例子:
DATA lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE i.
上面程序中“DATA”是什么意思?
‘DATA’是ABPA中的一个预定义类型,和其他预定义类型(如I,char10等),但是不是一个完整的数据类型(一般数据类型)。
这debugging模式下理解上面的两个程序结构。
在程序中设置断点,分析lr_Data的变化。
双击lr_Data。如果查看pointed area,初始lr_Data并未指向任何内容。
如下图,执行一步。
此时,lr_data初始化为int类型的初始值。
意味着通过执行
CREATE DATA lr_data TYPE i.
语句,初始化了lr_data的值为0.
这里的lr_data是“引用变量”,不是普通的变量。
双击lr_data后,进一步查看该变量。
- REF TO \TYPE=I,是类型“I”的引用。
- {A:1*\TYPE=I}, 是我们创建数据的地址。
(PS:这里我们不能像查看普通变量一样,双击变量名查看该引用变量的具体内容。
如果想查看该变量的内容/值,可以通过点击下图的Hook symbol)
查看结果图下图。
另一种方式是在debugging模式下,在变量后添加->*可以查看数据。
-> :表示指向地址
* :表示内容
->*:表示该地址的内容
如下图,我们在程序中给引用变量赋值:
发生了编译错误:
什么是 de Reference?(重引用?)
重引用 '->',通过指定数据对象的内存,来指定特定的数据对象。
-> 表示引用
->*表示重引用,或者表示给相应的地址指定值。
因此,在我们的例子中,通过在引用变量后简单的添加->*符号,是不正确的。
那么如何给引用变量指定数值呢?
只有通过Field-symbols的方式访问引用变量。
因为Field symbol是SAP提供的唯一方式,来访问数据对象地址的内容。(前面部分已经介绍表示FS指向数据对象的内容)
特别注意:
需要特别注意的是,如果想访问特定的地址,或者给特定地址指定数值。需要把数据对象的地址,指定到Field Symbol上。如果不知道正在方位的数据对象指向哪个数据引用,那么Field Symbol必须声明为一般数据类型(接下来将要讨论)。
下面开始讨论DATA REFERENCES的两种类型:
Known Type
Un Known Type
下面通过两个实例来讨论:
Known Type
1、已知的数据引用(数据变量一定)
*Creat the know data variable using data reference
DATA lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE i.
*Declare a field-symbol of type i
FIELD-SYMBOLS: <fs_data> TYPE i.
*Assign the value of lr_data to field symbols <fs_data>
ASSIGN lr_data->* TO <fs_data>.
*Assign populate the values into that address through field symbol
<fs_data> = 10.
WRITE: / <fs_data>.
执行该程序,输出结果为:
10
2、已知数据引用(结构体)
*Creat the known structure using data reference
DATA lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE sflight.
*Declare a field-symbol of type i
FIELD-SYMBOLS: <fs_sflight> TYPE sflight.
*Assign the value of lr_data to field symbols <fs_sflight>
ASSIGN lr_data->* TO <fs_sflight>.
*Assign populate the values into that address through field symbol
IF sy-subrc IS INITIAL.
<fs_sflight>-carrid = 123.
<fs_sflight>-connid = 456.
ENDIF.
WRITE: / <fs_sflight>-carrid,
<fs_sflight>-connid.
执行结果为:
3、已知数据引用(内表)
*Creat the known inernal table using data reference
DATA lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE STANDARD TABLE OF sflight.
*Declare a field-symbol of type i
TYPES: tt_sflight TYPE STANDARD TABLE OF sflight.
FIELD-SYMBOLS: <ft_sflight> TYPE tt_sflight.
*Assign the value of lr_data to field symbols <ft_sflight>
ASSIGN lr_data->* TO <ft_sflight>.
*Assign populate the values into that address through field symbol
IF sy-subrc IS INITIAL.
FIELD-SYMBOLS: <fs_sflight> TYPE sflight.
APPEND INITIAL LINE TO <ft_sflight> ASSIGNING <fs_sflight>.
<fs_sflight>-carrid = 1.
<fs_sflight>-connid = 11.
APPEND INITIAL LINE TO <ft_sflight> ASSIGNING <fs_sflight>.
<fs_sflight>-carrid = 2.
<fs_sflight>-connid = 22.
APPEND INITIAL LINE TO <ft_sflight> ASSIGNING <fs_sflight>.
<fs_sflight>-carrid = 3.
<fs_sflight>-connid = 33.
ENDIF.
*display
LOOP AT <ft_sflight> ASSIGNING <fs_sflight>.
WRITE: /
<fs_sflight>-carrid,
<fs_sflight>-connid.
ENDLOOP.
Un Known Type
下面我们通过实例来讨论Unknown data reference
当不确定我们要使用何种类型的数据对象时,或者何种类型的表类型时,则会考虑Unknown data reference。但是需要明确的是我们要创建的是变量?结构体或者内表?
SAp提供了一些通用数据类型(Genericdata types),比如:
Type any:用于类型未知的变量和结构体定义;
Type any table:用于类型未知的表类型;
Type ref to data;
Type object等。
注意:Generic data types只能用于Fieldsymbols
1、类型未知的数据引用:
*parameter for user input
PARAMETERS: p_var TYPE string.
DATA lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE (p_var).
*any type
FIELD-SYMBOLS: <fs> TYPE any.
ASSIGN lr_data->* TO <fs>.
IF sy-subrc IS INITIAL.
<fs> = '100'.
ENDIF.
WRITE: <fs>.
2、类型未知的结构体引用:
*parameter for user input
PARAMETERS: p_var TYPE string.
DATA lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE (p_var).
*any type
FIELD-SYMBOLS: <fs> TYPE any.
ASSIGN lr_data->* TO <fs>.
SELECT SINGLE *
FROM (p_var)
INTO <fs>.
IF sy-subrc IS INITIAL.
FIELD-SYMBOLS: <fs_area> TYPE any.
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE <fs> TO <fs_area>.
" this statement gets components of structure one by one
" form <fs> and send to <fs_area>
" when wo do not konw the fields of structure.do this process.
IF sy-subrc = 0.
WRITE: / <fs_area>.
ELSE.
EXIT.
ENDIF.
ENDDO.
ENDIF.
3、类型未知的表引用:
*Parameter for user input
PARAMETERS: p_var TYPE string.
DATA: lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE TABLE OF (p_var).
"As we dont know what type of structure we have to create, let us declare field symbol dynamically as follows
FIELD-SYMBOLS: <ft_table> TYPE ANY TABLE. "key word any table is used for declaration of unknown field symbol
ASSIGN lr_data->* TO <ft_table>.
IF sy-subrc IS INITIAL.
SELECT * FROM (p_var) INTO TABLE <ft_table> UP TO 5 ROWS.
IF sy-subrc = 0.
DATA: r_data TYPE REF TO cl_salv_table.
CALL METHOD cl_salv_table=>factory
IMPORTING
r_salv_table = r_data
CHANGING
t_table = <ft_table>.
ENDIF.
r_data->display( ).
ENDIF.