运行时类型识别(RTTI) (★★★) #dynamic-prog #rtti #data-types
概述 运行时类型识别(RTTI)允许使用类型描述对象在运行时描述数据类型和对象类型 。每种 ABAP 类型映射到一个特定的 RTTI 类实例,提供关于类型结构、组件和属性的元数据。
RTTI 类层次结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 CL_ABAP_TYPEDESCR(根类) | kind: kind_elem, kind_struct, kind_table, kind_ref, kind_class, kind_intf | 方法: describe_by_name(), describe_by_data(), describe_by_object_ref() | +-- CL_ABAP_DATADESCR | | +-- CL_ABAP_ELEMDESCR | | 内置类型: GET_I, GET_F, GET_C, GET_STRING, GET_P ... | | DDIC: get_ddic_field_list() | | | +-- CL_ABAP_REFDESCR | | get_ref_type() -> 基础类型描述符 | | | +-- CL_ABAP_STRUCTDESCR | | get_components() -> 组件表 | | get_ddic_field_list() -> DDIC 字段信息 | | | +-- CL_ABAP_TABLEDESCR | | get_table_line_type() -> 行类型描述符 | | key: 表键信息 | | | +-- CL_ABAP_ENUMDESCR | +-- CL_ABAP_OBJECTDESCR +-- CL_ABAP_CLASSDESCR | 方法、属性、继承信息 +-- CL_ABAP_INTFDESCR 接口方法信息
关键工厂方法(CL_ABAP_TYPEDESCR)
方法
用途
返回值
describe_by_name( name )
获取命名类型的描述符(DDIC/全局)
类型描述符对象
describe_by_data( dobj )
从数据对象获取描述符
类型描述符对象
describe_by_object_ref( ref )
从对象引用获取描述符
对象类型描述符
describe_by_ref( ref )
从数据引用获取描述符
类型描述符对象
1 2 3 4 5 6 7 8 " 通过数据对象 DATA(lo_descr) = cl_abap_typedescr=>describe_by_data( lv_value ). " 通过类型名称 DATA(lo_descr) = cl_abap_typedescr=>describe_by_name( 'STRING' ). " 通过对象引用 DATA(lo_obj_descr) = cl_abap_typedescr=>describe_by_object_ref( oref ).
KIND 属性值
常量
值
描述符类
含义
kind_elem
E
CL_ABAP_ELEMDESCR
基本类型
kind_struct
S
CL_ABAP_STRUCTDESCR
结构类型
kind_table
T
CL_ABAP_TABLEDESCR
内表类型
kind_ref
R
CL_ABAP_REFDESCR
引用类型
kind_class
C
CL_ABAP_CLASSDESCR
类类型
kind_intf
I
CL_ABAP_INTFDESCR
接口类型
1 2 3 4 5 6 7 8 CASE lo_descr->kind. WHEN cl_abap_typedescr=>kind_elem. " 基本类型 WHEN cl_abap_typedescr=>kind_struct. " 结构 WHEN cl_abap_typedescr=>kind_table. " 内表 ENDCASE.
CL_ABAP_ELEMDESCR 描述基本(内置)类型。
1 2 3 4 5 6 7 8 DATA: lo_elem TYPE REF TO cl_abap_elemdescr. lo_elem ?= cl_abap_typedescr=>describe_by_data( lv_string ). " 访问属性 WRITE: / lo_elem->type_kind, " 类型种类字符 lo_elem->length, " 内部长度 lo_elem->output_length, " 输出长度 lo_elem->decimals. " 小数位数(类型 p)
属性
类型
含义
type_kind
typekind
单字符:C、N、I、P、F、D、T、g(string)、y(xstring) …
length
i
内部长度(字节)
output_length
i
输出长度
decimals
i
小数位数
内置类型的静态工厂方法
方法
创建以下类型的描述符
GET_C( len )
类型 c,指定长度
GET_N( len )
类型 n,指定长度
GET_X( len )
类型 x,指定长度
GET_P( len decimals )
类型 p,指定长度和小数位
GET_I()
类型 i
GET_F()
类型 f
GET_STRING()
类型 string
GET_XSTRING()
类型 xstring
CL_ABAP_STRUCTDESCR 描述结构化类型并提供对组件的访问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 DATA: lo_struct TYPE REF TO cl_abap_structdescr. DATA: lt_comp TYPE cl_abap_structdescr=>component_table. lo_struct ?= cl_abap_typedescr=>describe_by_data( ls_any_struct ). " 获取组件列表 lt_comp = lo_struct->get_components( ). LOOP AT lt_comp INTO DATA(ls_comp). WRITE: / ls_comp-name, ls_comp-type->kind. ENDLOOP. " 获取 DDIC 字段列表(用于 DDIC 结构) DATA: lt_ddic TYPE ddfields. lt_ddic = lo_struct->get_ddic_field_list( ).
方法
返回值
用途
get_components()
component_table
所有组件及名称、类型描述符
get_ddic_field_list()
ddfields
DDIC 元数据(域、数据元素、文本)
组件表结构
字段
类型
内容
name
string
组件名称
type
REF TO cl_abap_datadescr
组件的类型描述符
as_include
abap_bool
是否为 include 结构?
suffix
string
include 命名冲突的后缀
CL_ABAP_TABLEDESCR 描述内表类型。
1 2 3 4 5 6 7 8 9 10 11 DATA: lo_table TYPE REF TO cl_abap_tabledescr. DATA: lo_line TYPE REF TO cl_abap_datadescr. lo_table ?= cl_abap_typedescr=>describe_by_data( lt_any_table ). " 获取行类型 lo_line = lo_table->get_table_line_type( ). " 访问表类别和键 WRITE: / lo_table->table_kind, " tablekind_standard/sorted/hashed lo_table->key. " 键信息
属性
含义
table_kind
tablekind_standard、tablekind_sorted、tablekind_hashed
key
键组件和键类别
key_defkind
键定义类型:default、table line、user、empty
方法
返回值
用途
get_table_line_type()
REF TO cl_abap_datadescr
行类型的描述符
CL_ABAP_REFDESCR 描述引用类型。
1 2 3 4 5 DATA: lo_ref TYPE REF TO cl_abap_refdescr. DATA: lo_base TYPE REF TO cl_abap_datadescr. lo_ref ?= cl_abap_typedescr=>describe_by_data( dref_any ). lo_base = lo_ref->get_referenced_type( ). " 它指向什么?
CL_ABAP_OBJECTDESCR(及子类) 描述类和接口。
1 2 3 4 5 6 7 8 DATA: lo_class TYPE REF TO cl_abap_classdescr. lo_class ?= cl_abap_typedescr=>describe_by_object_ref( oref ). " 访问方法和属性 LOOP AT lo_class->methods INTO DATA(ls_meth). WRITE: / ls_meth-name. ENDLOOP.
子类
关键属性
CL_ABAP_CLASSDESCR
methods、attributes、super_class
CL_ABAP_INTFDESCR
methods、attributes(接口的)
DESCRIBE FIELD 语句 一种更简单的、基于语句的基本类型信息获取方式:
1 2 3 4 5 6 7 8 9 10 DATA: lv_type TYPE c LENGTH 1. DATA: lv_length TYPE i. DATA: lv_olength TYPE i. DATA: lv_decimals TYPE i. DESCRIBE FIELD lv_data TYPE lv_type LENGTH lv_length IN BYTE MODE OUTPUT-LENGTH lv_olength DECIMALS lv_decimals.
附加项
返回值
说明
TYPE typ
单字符类型种类
C、I、P、F、g 等
LENGTH n
内部长度
使用 IN BYTE MODE 或 IN CHARACTER MODE
OUTPUT-LENGTH n
输出长度
–
DECIMALS n
小数位数
仅对类型 p 有意义
DESCRIBE FIELD 在快速检查时更简单。RTTI 提供更丰富的元数据并能处理复杂类型(结构、表)。超出基本类型/长度查询的场景优先使用 RTTI。
RTTI 类型解析流程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 数据对象 / 类型名称 / 对象引用 | v describe_by_*() --> CL_ABAP_TYPEDESCR | | v v 检查 ->kind 向下转型 (?=) 到具体类 | | v v kind_elem? --> CL_ABAP_ELEMDESCR --> type_kind, length, decimals kind_struct? --> CL_ABAP_STRUCTDESCR --> get_components(), get_ddic_field_list() kind_table? --> CL_ABAP_TABLEDESCR --> get_table_line_type(), key kind_ref? --> CL_ABAP_REFDESCR --> get_referenced_type() kind_class? --> CL_ABAP_CLASSDESCR --> methods, attributes kind_intf? --> CL_ABAP_INTFDESCR --> methods, attributes
考试/测试模式
关键词 / 短语
答案
“RTTI 根类”
CL_ABAP_TYPEDESCR
“从数据对象获取描述符”
describe_by_data( dobj )
“从类型名称获取描述符”
describe_by_name( 'TYPE_NAME' )
“从对象引用获取描述符”
describe_by_object_ref( oref )
“KIND 属性值”
kind_elem、kind_struct、kind_table、kind_ref、kind_class、kind_intf
“获取结构组件”
CL_ABAP_STRUCTDESCR=>get_components()
“获取 DDIC 字段信息”
CL_ABAP_STRUCTDESCR=>get_ddic_field_list()
“获取表行类型”
CL_ABAP_TABLEDESCR=>get_table_line_type()
“DESCRIBE FIELD 返回类型种类”
单字符:TYPE typ 附加项
“RTTI 向下转型运算符”
?=(从基类到具体描述符的窄化转型)
“基本类型属性”
type_kind、length、output_length、decimals
“引用类型的基础类型”
CL_ABAP_REFDESCR=>get_referenced_type()
相关笔记