zoukankan      html  css  js  c++  java
  • 动态编程

    动态的基本语法

    image100

    动态内容必须是大写

    多种不同的动态编程

    image101

    动态字段

    image102

    arbitrary:任意的

    动态类型

    image103

    指定结构、内表组件字段的动态

    image104

    Open SQL语句中的动态

    image105

    动态访问程序

    image106

    创建与运行临时Subroutines

    image107

     

    image108

    上面讲的是对一个存在的物理程序文件进行动态操作的过程。如果想要不生成的物理文件,则可以为某个程序临时动态的创建Subroutines

    GENERATE SUBROUTINE POOL <itab> NAME <prog> [<options>].

    该语句将会在当前running programmain memory area中创建临时subroutine pool,其源代码为<itab>中的内容。<prog>是类型为C类型8位长度的变量,用来接受该语句返回动态生成的subroutine pool的名字。你可以使用这个名字<prog>来调用通过<itab>内表动态生成的外部subroutines

    动态生成的subroutine pool只会在生成它的程序里运行期间存在,并且也只能从生成它的程序里调用它。你可以为一个程序最多创建36subroutine pools

    如果在生成期间发行了错误,则SY-SUBRC将设置为8

     

    语句中的[<options>]可选项如下:

    ? MESSAGE <mess>

    如果发生语法错误,则会存储这些错误消息

    ? INCLUDE <incl>

    如果发生语法错误,则该字段会存储了问题发生的include program的名字

    ? LINE <line>

    如果发生语法错误,则该字段存储了发生错误的行

    ? WORD <word>

    如果发生语法错误,该字段存储了wrong word (发生错误的单词)

    ? OFFSET <offs>

    如果发生语法错误,该字估存储了wrong word所在行的偏移量位置

    ? TRACE-FILE <trac>

    如果发生语法错误,将会切换到trace mode ,并且该字段存储了traceoutput

     

    INSERT REPORT相比,GENERATE SUBROUTINE POOL语句具有更好的性能,另外,生成的临时程序不会覆盖现有的程序

     

    REPORT zmaster2.
    DATA: code(72) OCCURS 10,
          prog
    (8),
          msg
    (120),
          lin
    (3),
          wrd
    (10),
          off
    (3).
    APPEND 'PROGRAM SUBPOOL.' TO code.
    APPEND 'FORM DYN1.' TO code.
    APPEND 'WRITE / ''Hello, I am the temporary subroutine DYN1!''.' TO code.
    APPEND 'ENDFORM.' TO code.
    APPEND 'FORM DYN2.' TO code.

    "此处的WRITE故意写成了WRIT,运行时会出编译错误
    APPEND 'WRIT / ''Hello, I am the temporary subroutine DYN2!''.' TO code.
    APPEND 'ENDFORM.' TO code.
    "临时生成外部程序的
    Form
    GENERATE SUBROUTINE POOL code NAME prog
                                 
    MESSAGE
    msg
                                 
    LINE
    lin
                                 
    WORD
    wrd
                                 
    OFFSET off.

    IF sy-subrc <> 0.
     
    WRITE: / 'Error during generation in line: ', lin,
             /
    'Msg:' , msg,
             /
    'Word:', wrd, 'at offset', off.
    ELSE.
     
    WRITE: / 'The name of the subroutine pool is', prog.
     
    "动态调用临时生成的Form
     
    PERFORM dyn1 IN PROGRAM (prog).
     
    PERFORM dyn2 IN PROGRAM (prog).
    ENDIF.

    如果将第6行的WRITE修改成WRIT时,运行时会显示编译出错的结果:

    image109

     

    否则调用临时生成的外部程序Form成功结果:

    image110

    RTTSRun Time Type Services

    Run Time Type Services (RTTS)是以以下三项为基础的:

    1、  Type identification and description at run time (formerly RTTI)

    2、  Dynamic type creation (RTTC)

    3、  Implemented as system classes

    数据变量反射

    TYPES my_type TYPE i.
    DATA: my_data   TYPE my_type,
          descr_ref
    TYPE ref to cl_abap_typedescr.

      descr_ref
    = cl_abap_typedescr
    =>describe_by_data( my_data ).
     
    WRITE: / 'Typename:', descr_ref->absolute_name.
     
    WRITE: / 'Kind    :', descr_ref->type_kind.
     
    WRITE: / 'Length  :', descr_ref->length.
     
    WRITE: / 'Decimals:', descr_ref->decimals.

     

    Typename:PROGRAM=ZJZJ_TEST3TYPE=MY_TYPE

    Kind    : I

    Length  :          4

    Decimals:          0

    对象引用反射

    DATA: oref1 TYPE REF TO object,
          oref2
    TYPE REF TO object.

    DATA: descr_ref1 TYPE REF TO cl_abap_typedescr,
          descr_ref2
    TYPE REF TO cl_abap_typedescr,
          mess      
    TYPE string.

    TRY.
       
    CREATE OBJECT: oref1 TYPE ('C1'),
                       oref2
    TYPE ('C2').
    CATCH cx_sy_create_object_error.
       
    MESSAGE 'Create object error!' TYPE 'I' DISPLAY LIKE 'E'.
       
    LEAVE PROGRAM.
    CATCH cx_root.
       
    MESSAGE 'Other error!' TYPE 'I' DISPLAY LIKE 'E'.
       
    LEAVE PROGRAM.

    ENDTRY.
    "根据对象引用来进行反射
    descr_ref1
    = cl_abap_typedescr
    =>describe_by_object_ref( oref1 ).
    descr_ref2
    = cl_abap_typedescr
    =>describe_by_object_ref( oref2 ).

    TRY.
       
    IF descr_ref1 <> descr_ref2.
         
    RAISE EXCEPTION TYPE conv_exc.
       
    ELSE.
          oref1
    = oref2.
       
    ENDIF.
    CATCH conv_exc.
        mess
    `Assignment from type `   &&
                descr_ref2
    ->
    absolute_name &&
               
    ` to `                   
    &&
                descr_ref1
    ->
    absolute_name &&
               
    ` not allowed!`.

       
    MESSAGE mess TYPE 'I' DISPLAY LIKE 'E'.
    ENDTRY.

    image111

    RTTS系统类结构图

     

    image112

     

    CL_ABAP_TYPEDESCR

      |

      |--CL_ABAP_DATADESCR

      |   |

      |   |--CL_ABAP_ELEMDESCR

      |   |--CL_ABAP_REFDESCR

      |   |--CL_ABAP_COMPLEXDESCR

      |       |

      |       |--CL_ABAP_STRUCTDESCR

      |       |--CL_ABAP_TABLEDESCR

      |

      |--CL_ABAP_OBJECTDESCR

         |

         |--CL_ABAP_CLASSDESCR

         |--CL_ABAP_INTFDESCR

     

    ABAP中类型的原理

    image113

    immutable:不可变

    每种类型都会有一个运行时类型对象

    每种类型对象都会对应到相应的类型

    类型对象是一个RTTS类的一个实例

     

    类型对象是不可变的

    类型对象描述了所有类型的属性

    类型对象可以用来代替类型名

    How to get a Type Object获取类型对象

    l  Get type object by type name通过类型名获取

    DATA: structtype  TYPE REF TO cl_abap_structdescr.
    structtype ?= cl_abap_typedescr=>
    describe_by_name( 'spfli' ).

    l  Get type object from a data object通过数据对象获取

    DATA: datatype TYPE REF TO cl_abap_datadescr,
    field(5) TYPE c
    .
    datatype ?= cl_abap_typedescr=>
    describe_by_data( field ).

    l  Get elementary types直接获取基本类型对象

    DATA: elemtype TYPE REF TO cl_abap_elemdescr.
    elemtype = cl_abap_elemdescr=>
    get_i( ).

    elemtype = cl_abap_elemdescr=>
    get_c( 20 ).

    Working with Type Objects通过类型对象创建数据或对象

    l  Create a data object of a specific type using a type object

    DATA: dref TYPE REF TO data,
    c20type
    TYPE REF TO
    cl_abap_elemdescr.
    c20type = cl_abap_elemdescr=>get_c(
    10
    ).
    CREATE DATA
    dref
    TYPE HANDLE c20type.

     

    l  Casting of a field symbol using a type object

    DATA: x20Type TYPE REF TO cl_abap_elemdescr.
    FIELD-SYMBOLS: <fs> TYPE any
    .
    x20Type = cl_abap_elemdescr=>get_x(
    20
    ).
    ASSIGN dref->* TO <fs> CASTING
     
    TYPE HANDLE x20Type.

    Principles(实践) of Dynamic Type Creation

    Dynamically created types are

    ?? transient (exist only for the lifetime of the internal mode)

    ?? program local (live only in roll area)

    ?? anonymous (no name, only accessible by type object)

     

    l  Implicit(隐式) type creation

    only for table and reference types

    CREATE DATA dref TYPE TABLE OF type.
    CREATE DATA dref TYPE
     REF TO type.

     

    l  Explicit(显示) Type creation

    factory method CREATE( ) in RTTS classes

    structType = CL_ABAP_STRUCTDESCR=>create( compTab ).

    动态创建内表Dynamic Creation of Table Types

    image114

    image115

     

    这些默认的值是该类中定义的常量,可以直接使用

    image116

    动态创建引用类型Dynamic Creation of Reference Types

    image117

     

    image118

    动态创建结构类型Dynamic Creation of Structured Types

    image119

    类型component_table是一种类型cl_abap_structdescr=>component_table的内表,其内表行结构如下:

      begin of abap_componentdescr,
        name      
    type
    string,
       
    type       type ref to
    cl_abap_datadescr,
        as_include 
    type
    abap_bool,
        suffix    
    type
    string,
     
    end of
    abap_componentdescr,

     

    image120

    image121

    Analyzing Structures with Includes

    image122

    image123

     

    image124

    image125

    image126

    image127

    image128

    动态创建基本类型、结构体、内表

    ****************** hardcoded "old style" local type*******************
    * This is a normal hardcoded local type
    TYPES : BEGIN OF typ_hardcoded,
            l_count
    TYPE i
    .
           
    INCLUDE STRUCTURE
      sflight.
    TYPES: END OF
    typ_hardcoded.
    * create a table based on hardcoded type

    DATA : lt_hardcoded TYPE TABLE OF typ_hardcoded.

    ****************** dynamic "new wave" local type *******************

    *TYPES: typ_count TYPE i.
    FIELD-SYMBOLS :<fs_str> ,"指向结构
                   <fs_itab>
    TYPE ANY TABLE,"指向内表
                   <fs_i> .
    DATA: dref_str TYPE REF TO data,
          dref_tab
    TYPE REF TO data
    ,
          dref_i
    TYPE REF TO data
    ,
      itab_type
    TYPE REF TO
     cl_abap_tabledescr,
      struct_type
    TYPE REF TO
     cl_abap_structdescr,
      elem_type
    TYPE REF TO
     cl_abap_elemdescr,

    table_type TYPE REF TO cl_abap_tabledescr,
      comp_tab
    TYPE cl_abap_structdescr=>component_table WITH HEADER LINE.
    "========
    动态创建基本类型数据对象
    elem_type ?= cl_abap_elemdescr=>describe_by_name(
    'I' )."根据类型名称来创建类型对象
    "或者是
    *elem_type ?= cl_abap_elemdescr=>get_i( ).
    CREATE DATA dref_i TYPE HANDLE elem_type ."动态的创建基本类型数据对象
    "========动态创建结构体数据对象
    * We read information about each fields of SFLIGHT (see ABAP FAQ #2)
    struct_type ?= cl_abap_typedescr=>describe_by_name(
    'SFLIGHT' )."结构类型
    * we read all fleids of SFLIGHT and create a component table
    comp_tab[] = struct_type->get_components( ).
    "组成结构体的各个字段组件
    * We add manually the counter 向结构中动态的新增一个成员
    comp_tab-name =
    'L_COUNT'."为结构新增一个成员
    comp_tab-
    type = elem_type."新增成员的类型对象
    INSERT comp_tab INTO comp_tab INDEX 1.
    * we create the structure
    动态创建结构类型对象
    struct_type = cl_abap_structdescr=>create( comp_tab[] ).
    CREATE DATA dref_str TYPE HANDLE struct_type."使用结构类型对象来创建结构对象
    ASSIGN dref_str->* TO <fs_str>."将字段符号指向新创建出来的结构对象
    "========动态创建内表类型对象
    * ... and the internal table 基于结构类型对象创建内表类型对象
    itab_type = cl_abap_tabledescr=>create( struct_type ).
    * The new thing here is the "type handle" which create a pointer to a handle
    CREATE DATA dref_tab TYPE HANDLE itab_type."使用内表类型对象来创建内表类型
    * we finally assign a field symbol to the pointer because we cannot directly access a pointer.
    ASSIGN dref_tab->* TO <fs_itab>."将字段符号指向新创建出来的内表对象
    * At the end of this small program, internal table lt_hardcoded and <fs_itab> are the same

     

    "========给现有的内表动态的加一列

              table_type ?= cl_abap_tabledescr=>describe_by_data( itab ).
              struct_type ?= table_type
    ->get_table_line_type( )
    .
              comp_tab[]
    = struct_type->get_components( )
    .
              comp_tab
    -name = 'FIDESC'.

              comp_tab
    -type = cl_abap_elemdescr=>get_c( 120 ).
             
    INSERT comp_tab INTO comp_tab INDEX 2.


              struct_type
    = cl_abap_structdescr=>create( comp_tab[] ).
              itab_type
    = cl_abap_tabledescr=>create( struct_type )
    .
             
    CREATE DATA dref_tab TYPE HANDLE itab_type
    .

     

    另外,在ALV中可以根据FieldCat来动态创建内表:

    rt_fieldcatalog type lvc_t_fcat

      call method cl_alv_table_create=>create_dynamic_table
       
    exporting
          it_fieldcatalog
    = rt_fieldcatalog[]
       
    importing

          ep_table       
    = g_table.

    动态访问指定的数据库表

    *================================================================
    PARAMETERS     tabnam(10) TYPE c  DEFAULT 'SFLIGHT'.

    DATA           dy_struc   TYPE REF TO data
    .
    FIELD-SYMBOLS  <fs_struc> TYPE ANY
    .
    FIELD-SYMBOLS  <feld>     TYPE ANY
    .
    *================================================================

    START-
    OF-SELECTION.
     
    "
    基于数据词典类型动态创建结构
     
    CREATE DATA dy_struc TYPE (tabnam).
     
    ASSIGN dy_struc->* TO
    <fs_struc>.

     
    SELECT * FROM (tabnam) INTO
    <fs_struc>.
       
    NEW-LINE
    .
       
    DO
    .
         
    "
    动态访问内表内容
         
    ASSIGN COMPONENT sy-index OF STRUCTURE <fs_struc> TO <feld>.
         
    IF sy-subrc NE 0
    .
           
    EXIT
    .
         
    ENDIF
    .
         
    WRITE AT (10
    ) <feld>.
       
    ENDDO
    .
     
    ENDSELECT
    .

    TOP-
    OF-PAGE
    .
     
    DATA  struct_type   TYPE REF TO
    cl_abap_structdescr.
     
    DATA  component  TYPE cl_abap_structdescr=>component_table WITH HEADER LINE
    .
     
    "
    获取结构对象的结构类型对象
      struct_type ?= cl_abap_typedescr=>describe_by_data( <fs_struc> ).
     
    NEW-LINE.
     
    component
    []  = struct_type->get_components( ).
     
    "
    遍历结构类型对象,输出结构的每个成员名称
     
    LOOP ATcomponent.
       
    WRITE AT (10) component
    -name.
     
    ENDLOOP
    .
     
    ULINE
    .

  • 相关阅读:
    tcl中指定随机数种子
    redis的三种连接方式
    js代码统计table中某一列的值
    CRF从HMM的演进
    SVM中的一些问题
    bert损失函数
    SQL 注入笔记
    20200818 千锤百炼软工人第四十四天
    20200816 千锤百炼软工人第四十三天
    20200816 千锤百炼软工人第四十二天
  • 原文地址:https://www.cnblogs.com/jiangzhengjun/p/4293407.html
Copyright © 2011-2022 走看看