为什么 SAP 试图变得比它必须的更聪明并在以下情况下生成短转储?
REPORT zzy.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main.
PRIVATE SECTION.
TYPES:
BEGIN OF t_my_type,
hierlevel TYPE i,
groupname TYPE ktext,
result TYPE p LENGTH 9 DECIMALS 2,
END OF t_my_type,
tt_my_type TYPE HASHED TABLE OF t_my_type WITH UNIQUE KEY hierlevel groupname.
CLASS-METHODS:
change
CHANGING
cs_my_type TYPE t_my_type.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD main.
DATA:
lt_my_table TYPE tt_my_type.
INSERT VALUE #( hierlevel = 0 groupname = 'MY_GROUP' result = '0.0' ) INTO TABLE lt_my_table
ASSIGNING FIELD-SYMBOL(<fs_my_type>).
change(
CHANGING
cs_my_type = <fs_my_type>
).
ENDMETHOD.
METHOD change.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>main( ).
方法没有任何变化
change
但在我看到的短转储的描述中
字段
将分配一个新值,但该字段至少部分受到保护以防止更改。<FS_MY_TYPE>-HIERLEVEL
看来 SAP 试图变得比应有的更聪明。如果我实际上尝试更改关键字段之一,我会理解是否生成了短转储。为什么要这样设计?
我刚刚发现简短转储中的进一步描述有这样的
以下内容不受更改:
- 如果使用 ASSIGN 分配的字段是,则使用字段符号访问 部分或完全受到保护(例如内部的关键组件) SORTED 或 HASHED TABLE 类型的表)。
对我来说有点奇怪,但看起来像是一个设计决定。也许在技术上很难只检查实际受保护的字段。
使用
INSERT...ASSIGNING <fs_row>
语法时,您应该始终注意适用于相应字段符号的限制。根据 SAP 的说法,READ TABLE ...ASSIGNING <fs_row>
中存在的相同限制也适用于
INSERT
施工。特别是,它们是:
只要字段符号指向该行,就可以对 字段符号修改内表中的行。下列 限制适用于修改主要和次要的关键字段 表键:
- 排序表和散列表的主表键的关键字段 表是只读的,不得修改。这将使 内部表管理。尝试这样做通常会引发 无法处理的异常。
...
同样的限制也适用于内联声明。
正如我们在代码中看到的,您对方法的参数使用隐式传递引用声明。但按引用传递不会为参数创建任何本地数据对象,并且使用实际参数,这要求它们可写。这是你问题的关键。
有趣的是,我们可以将数据引用作为更改后的参数传递,并且它可以工作。系统允许您更改非关键字段而不会出错,并针对关键字段更改抛出一个简短的转储。
REPORT zzy.
CLASS lcl_main DEFINITION FINAL CREATE PRIVATE.
PUBLIC SECTION.
CLASS-METHODS:
main.
PRIVATE SECTION.
TYPES:
BEGIN OF t_my_type,
hierlevel TYPE i,
groupname TYPE ktext,
result TYPE p LENGTH 9 DECIMALS 2,
END OF t_my_type,
tt_my_type TYPE HASHED TABLE OF t_my_type WITH UNIQUE KEY hierlevel groupname.
CLASS-METHODS:
change
CHANGING
cs_my_type TYPE REF TO t_my_type.
ENDCLASS.
CLASS lcl_main IMPLEMENTATION.
METHOD main.
DATA:
lt_my_table TYPE tt_my_type.
DATA ls_ref TYPE REF TO t_my_type.
INSERT VALUE #( hierlevel = 0 groupname = 'MY_GROUP' result = '0.0' ) INTO TABLE lt_my_table
ASSIGNING FIELD-SYMBOL(<fs_my_type>).
GET REFERENCE OF <fs_my_type> INTO ls_ref.
change(
CHANGING
cs_my_type = ls_ref
).
write: | { <fs_my_type>-result }|.
ENDMETHOD.
METHOD change.
* cs_my_type->*-groupname = 'GRP2'. "Short dump: Assignment error: Overwriting of a protected field.
cs_my_type->*-result = '10.1'.
ENDMETHOD.
ENDCLASS.
START-OF-SELECTION.
lcl_main=>main( ).