ABAP method parameters

 

    DATA: lt_callstack   TYPE abap_callstack,
          ls_callstack   TYPE abap_callstack_line,
          lo_class_desc  TYPE REF TO cl_abap_classdescr,
          ls_method_desc TYPE abap_methdescr,
          ls_param_desc  TYPE abap_parmdescr.
    FIELD-SYMBOLS: <lv_value> TYPE any.

    CALL FUNCTION 'SYSTEM_CALLSTACK'
      EXPORTING
        max_level = 1
      IMPORTING
        callstack = lt_callstack.
    READ TABLE lt_callstack INTO ls_callstack INDEX 1.
    lo_class_desc ?= cl_abap_classdescr=>describe_by_name( cl_oo_classname_service=>get_clsname_by_include( ls_callstack-include ) ).
    READ TABLE lo_class_desc->methods INTO ls_method_desc WITH KEY name = ls_callstack-blockname.
    LOOP AT ls_method_desc-parameters INTO ls_param_desc.
      ASSIGN (ls_param_desc-name) TO <lv_value>.
      " ...

    ENDLOOP.

'ABAP > ABAP-OO' 카테고리의 다른 글

ABAP OOP tutorial  (0) 2021.05.31
[Link] ABAP OO 동영상 강좌  (0) 2016.11.16
[번역] ABAP RTTI 동적 스트럭쳐, 인터널테이블 생성  (0) 2014.03.24
ABAP 클래스 UML 표시  (0) 2011.12.21
[Link] ABAP Freak Show  (0) 2010.11.11

목차:
interface & class

abstract class(추상 클래스)

inheritance(상속)

redifine method(메소드 재정의) = Method overriding

Polymorphism(다형성)

아래 nugg 를 설치 합니다.

NUGG_$OOP_TUTORIAL.nugg
0.02MB


ZOOP_TUTORIAL

*&---------------------------------------------------------------------*
*& Report ZOOP_TUTORIAL
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zoop_tutorial.

* OOP tutorial
* 관계도:
* ZIF_OOP_VEHICLE interface 탈것
* - ZCL_OOP_HORSE class 말
* - ZCL_OOP_BUS abstract class 버스
*   - ZCL_OOP_CITY_BUS class 시내버스
*   - ZCL_OOP_EXPRESS_BUS class 고속버스
*     - ZCL_OOP_EXPRESS_BUS_X2 class 2배 고속버스
* - ZCL_OOP_CAR abstract class 승용차
*   - ZCL_OOP_CAR_K5 class 승용차 K5
*   - ZCL_OOP_CAR_K7 class 승용차 K7


* interface & class
DATA: lo_vehicle TYPE REF TO zif_oop_vehicle,
      lv_name    TYPE string,
      lv_speed   TYPE i.

* interface는 타입으로 사용할 수 있지만 class로 구현을 해야 객체를 생성할 수 있음.
*     "LO_VEHICLE" is not an object reference.
* CREATE OBJECT lo_vehicle.

* zcl_oop_horse 는 zif_oop_vehicle 인터페이스를 구현한 클래스 입니다.
* horse 객체를 생성할 수 있음.
CREATE OBJECT lo_vehicle TYPE zcl_oop_horse.
lo_vehicle->set_name( 'my horse' ).

lv_name = lo_vehicle->get_name( ).
lo_vehicle->drive(
  EXPORTING
    iv_direction = 'F'
  IMPORTING
    ev_speed     = lv_speed
).

WRITE:/ lv_name, lv_speed.



* abstract class(추상 클래스)
* zcl_oop_bus 는 zif_oop_vehicle 인터페이스를 구현한 추상 클래스 입니다.
* 추상 클래스는 구현을 가지고 있지만 생성 할 수 없음.
*   Instances of the abstract class "ZCL_OOP_BUS" cannot be generated.
*CREATE OBJECT lo_vehicle TYPE zcl_oop_bus.



* inheritance(상속)
* zcl_oop_city_bus 는 zcl_oop_bus 를 상속한 일반 (추상 아님) 클래스 입니다.
* city bus 객체를 생성할 수 있음.
CREATE OBJECT lo_vehicle TYPE zcl_oop_city_bus.
lo_vehicle->set_name( 'my city bus' ).

lv_name = lo_vehicle->get_name( ).
lo_vehicle->drive(
  EXPORTING
    iv_direction = 'F'
  IMPORTING
    ev_speed     = lv_speed
).

WRITE:/ lv_name, lv_speed.



* redifine method(메소드 재정의) = Method overriding
* zcl_oop_express_bus_x2 는 zcl_oop_express_bus 를 상속한 클래스 입니다.
* 상속 받은 다음 메소드에 로직을 추가 할 수 있습니다.
* zcl_oop_express_bus_x2 의 drive 메소드를 확인하세요.
CREATE OBJECT lo_vehicle TYPE zcl_oop_express_bus.
lo_vehicle->set_name( 'ex-bus' ).

lv_name = lo_vehicle->get_name( ).
lo_vehicle->drive(
  EXPORTING
    iv_direction = 'F'
  IMPORTING
    ev_speed     = lv_speed
).

WRITE:/ lv_name, lv_speed.


CREATE OBJECT lo_vehicle TYPE zcl_oop_express_bus_x2.
lo_vehicle->set_name( 'ex2-bus' ).

lv_name = lo_vehicle->get_name( ).
lo_vehicle->drive(
  EXPORTING
    iv_direction = 'F'
  IMPORTING
    ev_speed     = lv_speed
).

WRITE:/ lv_name, lv_speed.




* Polymorphism(다형성)
* TYPE 으로 선언한 변수의 하위의 상속받은 모든 클래스를 생성 할 수 있음.
CREATE OBJECT lo_vehicle TYPE zcl_oop_horse.
*CREATE OBJECT lo_vehicle TYPE zcl_oop_bus. " 추상 클래스는 생성 불가
CREATE OBJECT lo_vehicle TYPE zcl_oop_city_bus.
CREATE OBJECT lo_vehicle TYPE zcl_oop_express_bus.
CREATE OBJECT lo_vehicle TYPE zcl_oop_express_bus_x2.
*CREATE OBJECT lo_vehicle TYPE zcl_oop_car. " 추상 클래스는 생성 불가
CREATE OBJECT lo_vehicle TYPE zcl_oop_car_k5.
CREATE OBJECT lo_vehicle TYPE zcl_oop_car_k7.

DATA: lo_bus TYPE REF TO zcl_oop_bus.
*CREATE OBJECT lo_bus TYPE zcl_oop_horse. " 타입 일치 하지 않음.
*CREATE OBJECT lo_bus TYPE zcl_oop_bus.  " 추상 클래스는 생성 불가
CREATE OBJECT lo_bus TYPE zcl_oop_city_bus.
CREATE OBJECT lo_bus TYPE zcl_oop_express_bus.
CREATE OBJECT lo_bus TYPE zcl_oop_express_bus_x2.
*CREATE OBJECT lo_bus TYPE zcl_oop_car.  " 타입 일치 하지 않음.
*CREATE OBJECT lo_bus TYPE zcl_oop_car_k5.  " 타입 일치 하지 않음.
*CREATE OBJECT lo_bus TYPE zcl_oop_car_k7.  " 타입 일치 하지 않음.

DATA: lo_car TYPE REF TO zcl_oop_car.
*CREATE OBJECT lo_car TYPE zcl_oop_horse. " 타입 일치 하지 않음.
*CREATE OBJECT lo_car TYPE zcl_oop_bus.  " 타입 일치 하지 않음.
*CREATE OBJECT lo_car TYPE zcl_oop_city_bus.  " 타입 일치 하지 않음.
*CREATE OBJECT lo_car TYPE zcl_oop_express_bus.  " 타입 일치 하지 않음.
*CREATE OBJECT lo_car TYPE zcl_oop_express_bus_x2.  " 타입 일치 하지 않음.
*CREATE OBJECT lo_car TYPE zcl_oop_car. " 추상 클래스는 생성 불가
CREATE OBJECT lo_car TYPE zcl_oop_car_k5.
CREATE OBJECT lo_car TYPE zcl_oop_car_k7.

 

SAP YARD의 OOP 동영상 강좌 입니다.

 

http://www.sapyard.com/15-minutes-per-session-videos-for-abap-object-oriented-programming-refresher/

 

15 minutes per session Videos for ABAP Object Oriented Programming Refresher

TOPICS:

sap abap objects

C++에선 RTTI 라고 부르고 JAVA에선 Reflection 이라고 부르는 이것을 활용하면

실행중에 동적으로 타입을 생성하거나 타입 정보를 읽어서 활용 할 수 있습니다.

 

이글은 아래 링크의 원본 글에 대한 한글 번역 입니다. thanks to Niketh Reddy
http://abaperspace.blogspot.com/2013/12/rtts-run-time-type-services-part1.html
http://abaperspace.blogspot.com/2013/12/rtts-run-time-type-services-part2.html
http://abaperspace.blogspot.com/2013/12/rtts-run-time-type-services-part3.html

 

 

RTTS (Run Time Type Services) -- Part1 RTTI(Run Time Type Identification)

 

RTTS는 Run Time Type Services 의 약어입니다. RTTS는 타입정보를 찾을 수 있는 기능을 제공합니다. 또한 실행중에 동적으로 타입을 만들고 새로운 인스턴스를 생성할 수도 있습니다. 아래 그림처럼 여러 아밥 클래스에 계층 관계를 가지고 구현되었습니다. RTTS는 두가지 부분 RTTI (Run Time Type Identification) 와 RTTC(Run Time Type Creation) 로 구분할 수 있습니다. 이런 클래스를 동적 타입 처리 로직(예: 동적 인터널 테이블 정의, 라인 스트럭쳐 타입를 모르는 인터널 테이블 처리)에 활용 할 수 있습니다.

 

 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

 

Part 1 에서는 실행중에 타입(변수, 스트럭쳐, 인터널테이블) 정보를 가져오는 방법을 설명하겠습니다. 기본적으로 RTTI 서비스는 위 클래스 계층구조를 활용합니다. 이 글에서 클래스와 인터페이스에 대한 예제는 없지만 다른 타입정보에 대한 예제와 동일한 개념을 적용하여 쉽게 사용수 있을 것으로 예상합니다. 위 계층구조에서 각각의 말단부분이 하나씩 각자 타입을 담당합니다. 예를들어 CL_ABAP_ELEMDESCR 는 단일 변수, CL_ABAP_STRUCTDESCR 는 스트럭쳐, CL_ABAP_TABLEDESCR 는 인터널테이블을 담당합니다. 이런 관계를 알아두면 앞으로 경우에 맞는 클래스를 찾는데 도움이 될 것입니다.

 

클래스 CL_ABAP_TYPEDESCR 는 계층구조 최상위에 위치하고 있습니다. 이 클래스에 구현된 메소드 DESCRIBE_BY_DATA 와 DESCRIBE_BY_NAME 는 적절한 타입에 맞게 계층구조 하위에 있는 클래스 인스턴스를 생성하는 메소드입니다. 두 메소드중 어떤것을 써야 하는지 궁금하죠? 각각의 필요한 경우를 살펴보도록 하겠습니다. 만약 인스턴스/변수 가 있는 상황에서 시작한다면 DESCRIBE_BY_DATA 를 호출하세요. 반대로 인스턴스/변수는 없지만 그 타입을 알고 있다면 DESCRIBE_BY_NAME 를 호출하세요.

 

첫번째 예제 코드를 보겠습니다. 이 예제 코드는 변수로 부터 시작하는 DESCRIBE_BY_DATA 메소드와  타입 이름으로 부터 시작하는 DESCRIBE_BY_NAME 메소드를 활용하여 MATNR 타입의 정보를 읽어 오는 내용입니다. 두가지 경우 실제로 같은 타입에 대한 정보이기 때문에 처리 결과는 같은 내용이 두번 반복됩니다.

 

CL_ABAP_TYPEDESCR 클래스는 타입을 나타내는데 사용됩니다. DESCRIBE_BY_DATA, DESCRIBE_BY_NAME 메소드의 리턴값은 CL_ABAP_TYPEDESCR 클래스 타입의 오브젝트입니다. 이 클래스 자체로는 활용성이 떨어지므로 더 구체적인 변수/스트럭쳐/인터널테이블 등에 대한 정보를 얻기 위해 적당한 자식클래스(subclass)로 하향형변환(downcast 또는 widening 이라고 합니다. 반대말은 upcast 또는 narrowing 입니다.)하여 사용합니다.

DATA : material TYPE matnr.

DATA : lo_elem  TYPE REF TO cl_abap_elemdescr .


lo_elem ?= cl_abap_elemdescr=>describe_by_data( material ) .

PERFORM display_details USING lo_elem .


lo_elem ?= cl_abap_elemdescr=>describe_by_name( 'MATNR' ) .

PERFORM display_details USING lo_elem .


*&---------------------------------------------------------------------*

*&      Form  display_details

*&---------------------------------------------------------------------*

FORM display_details USING o_element TYPE REF TO cl_abap_elemdescr .

  WRITE : / 'Type Kind ' , o_element->type_kind ,

          / 'Length    ' , o_element->length ,

          / 'Abs. Name ' , o_element->absolute_name.

ENDFORM.                    "display_details

 

 

두번째 예제 코드를 보겠습니다. 딕셔너리 오브젝트 (데이터 엘리먼트)의 정보를 알고 싶다면 클래스 CL_ABAP_ELEMDESCR에 있는 메소드와 어트리뷰트를 사용하세요. 이 클래스의 메소드와 어트리뷰트에서는 데이터 타입에 해당하는 데이터 딕셔너리, 도메인 정보, 필드 레이블, 도메인 고정값 등을 알 수 있습니다.

DATA : lo_elem TYPE REF TO cl_abap_elemdescr .


lo_elem ?= cl_abap_typedescr=>describe_by_name('VBFA-VBTYP_N') .


DATA : ls_dfies  TYPE dfies .

DATA : li_values TYPE ddfixvalues .


IF lo_elem->is_ddic_type( )  = abap_true .

  WRITE : / 'Dictionary type' .

  ls_dfies  = lo_elem->get_ddic_field( ) .       "Dictionary information

  li_values = lo_elem->get_ddic_fixed_values( ) ."Domain fixed values

ENDIF.

 

 

세번째 예제 코드를 보겠습니다. 이번에는 스트럭쳐 타입에 대한 코드 입니다. CL_ABAP_STRUCTDESCR 클래스를 사용하여 동적으로 스트럭쳐에 들어 있는 필드(components) 이름을 찾아오는 데모입니다. 사용하는 클래스는 바뀌고 있지만 여전히 최상위 클래스의 CL_ABAP_TYPEDESCR=>DESCRIBE_BY_NAME 으로 시작하여 CL_ABAP_STRUCTDESCR의 인스턴스를 가져온다는 점 기억하세요.

TYPES: BEGIN OF ty_vbak,

        vbeln TYPE vbak-vbeln,

        erdat TYPE vbak-erdat,

        erzet TYPE vbak-erzet,

      END OF ty_vbak.


DATA : component TYPE abap_compdescr .

DATA : lo_struct TYPE REF TO cl_abap_structdescr .


lo_struct ?= cl_abap_typedescr=>describe_by_name('TY_VBAK') .


LOOP AT lo_struct->components INTO component .

  WRITE : / component-name .

ENDLOOP.

 

 

네번째 예제 코드를 보겠습니다. 여기에서는 CL_ABAP_TABLEDESCR 클래스를 사용하여 인터널 테이블의 다양한 정보를 찾아 보겠습니다. 어떤 종류의 인터널 테이블인지 즉 STANDARD, SORTED, HASHED 중에 어떤 종류인지 알 수 있습니다. 인터널 테이블 키 구성을 알 수 있습니다. 라인타입으로 사용된 스트럭쳐 정보를 알 수 있습니다. 스트럭쳐의 필드(component)와 각 필드의 데이터 엘리먼트 정보도 알 수 있습니다. 위에서 설명한 3개 예제를 모두 포함한 총정리라고 할 수 있습니다.

TYPES : tt_mara TYPE SORTED TABLE OF mara WITH UNIQUE KEY mandt matnr .

DATA : i_mara TYPE tt_mara .


DATA : lo_table_descr TYPE REF TO cl_abap_tabledescr ,

       lo_struc_descr TYPE REF TO cl_abap_structdescr,

       lo_elem_descr  TYPE REF TO cl_abap_elemdescr  ,

       ls_key         TYPE abap_keydescr             ,

       ls_component   TYPE abap_compdescr            .


* Query internal table

lo_table_descr ?= cl_abap_typedescr=>describe_by_data( i_mara ) .

WRITE : /  'Table kind ' , lo_table_descr->table_kind .


LOOP AT lo_table_descr->key INTO ls_key .

  WRITE : / 'Key ' , ls_key-name .

ENDLOOP.


*Structure of internal table

lo_struc_descr ?= lo_table_descr->get_table_line_type( ) .


LOOP AT lo_struc_descr->components INTO ls_component .

  WRITE : / 'Component name ' , ls_component-name .


* Element of stucture

  lo_elem_descr ?= lo_struc_descr->get_component_type( ls_component-name ) .

  WRITE :  'Kind ' , lo_elem_descr->type_kind , 'Length ' , lo_elem_descr->length .

ENDLOOP.

 

 

 

 

RTTS (Run Time Type Services) -- Part2 RTTC(Run Time Type Creation)

 

파트1에서는 RTTI에 대해서 다루었습니다. 이제 파트2에서 RTTC(Run time type creation)를 다루겠습니다.

여기에서는 변수, 스트럭쳐, 인터널테이블을 동적으로 생성하는 방법에 대해 설명하겠습니다.

효율적인 설명을 위해 스텝을 4단계로 나누어서 진행합니다.

 

1단계. 타입에 맞는 적절한 클래스의 인스턴스 생성하기/가져오기.

2단계. 데이터 레퍼런스(참조형 변수) 생성하기.

3단계. 데이터 레퍼런스를 필드심볼로 역참조하기.(역참조는 번역상 사용한 단어로 뜻은 레퍼런스를 필드심볼에 할당하여 값을 사용할 준비를 하는 동작을 의미 합니다)

4단계. 사용하기/값변경하기.

 

예제를 보겠습니다.

PERFORM create_element USING 'CHAR10'     'WE' .

PERFORM create_element USING 'VBPA-PARVW' 'WE' .


*&---------------------------------------------------------------------*

*&      Form  CREATE_ELEMENT

*&---------------------------------------------------------------------*

FORM create_element USING type_name TYPE any var_value TYPE any .


* Step 1

* Get instance of CL_ABAP_ELEMDESCR

  DATA : lo_element TYPE REF TO cl_abap_elemdescr .               

  lo_element ?= cl_abap_typedescr=>describe_by_name( type_name ). 


* Step 2

* Create data using instance of CL_ABAP_ELEMDESCR

  DATA : ref_dynamic_element TYPE REF TO data .

  CREATE DATA ref_dynamic_element TYPE HANDLE lo_element .  


* Step 3

* Dereferencing data

  FIELD-SYMBOLS : <fs_elem>  TYPE ANY .

  ASSIGN ref_dynamic_element->* TO <fs_elem> .


* Step 4

  <fs_elem> = var_value .


  WRITE : / 'Variable type' , type_name ,

            'Value'         , <fs_elem> .


ENDFORM .                    "CREATE_ELEMENT


*Output of above program


*Variable type CHAR10 Value WE

*Variable type VBPA-PARVW Value SH

 

 

주의: CREATE DATA 구문에 HANDLE 키워드를 사용하면 RTTS

 

type object에 의해 정의된 타입으로 데이터 오브젝트를 생성 할 수 있습니다.

 

위 코드는 실행중에 변수를 생성하고 값을 할당하고 다시 읽습니다. 1단계에서는 파트1에서 본 RTTS 클래스 계층구조에 있는  CL_ABAP_DATADESCR 클래스 (또는 자식 클래스)의 인스턴스를 생성합니다. 계층구조에서 어떤 클래스를 선택하는지는 무엇을 만들려고 하는지에 따라 다릅니다. 예를들어 인터널테이블을 생성하고자 한다면 CL_ABAP_TABLEDESCR 클래스를 사용해야 합니다. 선택한 RTTS 클래스는 아밥 실행중에 변수를 만들기 위한 정보를 가지고 있습니다. 2단계에서 CREATE DATA ref_variable TYPE HANDLE rtts_ref 구문을 사용하여 변수를 생성하고 그 레퍼런스를 ref_variable에 저장합니다. 이 ref_variable는 앞서 TYPE REF TO data 형태로 선언한 레퍼런스 변수 입니다. 2단계가 끝나면 동적으로 만든 타입으로 레퍼런스 변수를 생성하였지만 이 레퍼런스 변수는 직접 접근할 수 없습니다. 레퍼런스 변수에 접근하기 위해서는 반드시 필드심볼로 역참조하여야 합니다. 3단계와 4단계에서 역참조와 값변경을 합니다.

 

2단계와 3단계는 모든(변수, 스트럭쳐, 인터널테이블, 클래스객체 관계없이) 동적 타입 생성에 동일한 코드가 적용됩니다.

 

1단계와 4단계는 변수, 스트럭쳐, 인터널테이블, 클래스객체 어떤종류를 생성하느냐에 따라 코드가 변경됩니다.

스트럭쳐와 인터널테이블의 예제를 살펴보기 전에 정수형(integer) 변수를 생성하는 예제를 먼저 보겠습니다.

*Create integer type variable

DATA : lo_element TYPE REF TO cl_abap_elemdescr .

lo_element = cl_abap_elemdescr=>get_i( ) .


DATA : ref_dynamic_element TYPE REF TO data .

CREATE DATA ref_dynamic_element TYPE HANDLE lo_element .


FIELD-SYMBOLS : <fs_elem> TYPE ANY .

ASSIGN ref_dynamic_element->* TO <fs_elem> .


<fs_elem> = 10 .

WRITE : / <fs_elem> .


*Create character type variable

lo_element = cl_abap_elemdescr=>get_c( p_length = 10 ) .

CREATE DATA ref_dynamic_element TYPE HANDLE lo_element .

ASSIGN ref_dynamic_element->* TO <fs_elem> .

<fs_elem> = '10' .

WRITE : / <fs_elem> .

 

 

CL_ABAP_ELEMDESCR 클래스에는 기본형으로 변수를 생성할 수 있도록 GET_기본형 이름을 가진 스태틱 메소드가 여러개 있습니다. 위 예제에서는 GET_I와 GET_C를 사용하여 정수형(integer)과 문자형(charater) 변수를 생성하였습니다.

 

Method Description
GET_STRING Returns the Type Object for an Elementary Type string
GET_XSTRING Returns the Type Object for an Elementary Type xstring
GET_I Returns the Type Object for an Elementary Type i
GET_F Returns the Type Object for an Elementary Type f
GET_D Returns the Type Object for an Elementary Type d
GET_T Returns the Type Object for an Elementary Type t
GET_C Returns the Type Object for an Elementary Type c
GET_N Returns the Type Object for an Elementary Type n
GET_X Returns the Type Object for an Elementary Type x
GET_P Returns the Type Object for an Elementary Type p

 

다음 예제 코드는 스트럭쳐 입니다. 실행중에 동적으로 스트럭쳐를 생성하기 위해서는 CL_ABAP_STRUCDESCR의 레퍼런스가 필요합니다. CL_ABAP_STRUCDESCR 레퍼런스를 생성하는 방법은 2가지가 있습니다. CL_ABAP_TYPEDESCR=>DESCRIBE_BY_NAME 또는 CL_ABAP_STRUCTDESCR=>CREATE 를 필요한 상황에 맞게 사용하면 됩니다. 만약 스트럭쳐가 데이터 딕셔너리나 프로그램 내부에 정의된 것이라면 CL_ABAP_TYPEDESCR=>DESCRIBE_BY_NAME을 사용하면 됩니다. 아래 예제를 보시죠.

 

TYPE-POOLS : abap .


*Step 1

DATA : lo_struct TYPE REF TO cl_abap_structdescr .

lo_struct ?= cl_abap_typedescr=>describe_by_name('MARA') .


*Step 2

DATA : ref_dynamic_structure TYPE REF TO data .

CREATE DATA ref_dynamic_structure TYPE HANDLE lo_struct .


*Step 3

FIELD-SYMBOLS : <fs_struc> TYPE ANY .

ASSIGN ref_dynamic_structure->* TO <fs_struc> .


*Step 4

DATA : component TYPE abap_compdescr .

FIELD-SYMBOLS : <fs_elem> TYPE ANY .

LOOP AT lo_struct->components INTO component .

  ASSIGN COMPONENT component-name OF STRUCTURE <fs_struc> TO <fs_elem> .

  WRITE : / component-name , <fs_elem> .

ENDLOOP .

 

 

 

 

RTTS (Run Time Type Services) -- Part3 RTTC(Run Time Type Creation)

 

파트3에서는 동적으로 만든 스트럭쳐의 필드(component) 값에 접근하는 방법을 알려드립니다.

만약 필요한 스트럭쳐가 데이터 딕셔너리나 프로그램 내부에 정의된 것이 아니고 실행 중에 필드 목록을 구성하여 실행중에 달라질 수 있기에 미리 알 수 없는 경우가 있습니다. 이때 우리는 CL_ABAP_STRUCTDESCR=>CREATE 메소드를 사용합니다. 필드 목록을 인터널테이블 형태의 파라미터로 전달해야 합니다. 필드 목록은 이름과 타입정보(CL_ABAP_ELEMDESCR 레퍼런스 변수)를 가집니다. 스트럭쳐를 간단히 데이터 엘리먼트로 표현된 필드를 나열한 것이라 생각하면 쉽습니다. 아래 예제 코드는 기본형과 데이터 엘리먼트를 모두 가지고 있는 스트럭쳐를 정의합니다.

 

TYPE-POOLS : abap .

 

*Step 1

DATA : lo_struct        TYPE REF TO cl_abap_structdescr .

DATA : struc_components TYPE abap_component_tab         ,

       struc_component  TYPE abap_componentdescr        .

 

struc_component-name = 'SRNO' .

struc_component-type = cl_abap_elemdescr=>get_i( )  .

APPEND struc_component TO struc_components .

 

struc_component-name = 'COMMENTS' .

struc_component-type = cl_abap_elemdescr=>get_string( )  .

APPEND struc_component TO struc_components .

 

struc_component-name = 'MATERIAL' .

struc_component-type ?= cl_abap_typedescr=>describe_by_name('MATNR') .

APPEND struc_component TO struc_components .

 

lo_struct = cl_abap_structdescr=>create( struc_components ).

 

*Step 2

DATA : ref_dynamic_structure TYPE REF TO data .

CREATE DATA ref_dynamic_structure TYPE HANDLE lo_struct .

 

*Step 3

FIELD-SYMBOLS : <fs_struc> TYPE ANY .

ASSIGN ref_dynamic_structure->* TO <fs_struc> .

 

*Step 4

DATA : component TYPE abap_compdescr .

FIELD-SYMBOLS : <fs_elem> TYPE ANY .

LOOP AT lo_struct->components INTO component .

  ASSIGN COMPONENT component-name OF STRUCTURE <fs_struc> TO <fs_elem> .

  WRITE : / component-name , <fs_elem> .

ENDLOOP .

 

 

다음은 인터널테이블입니다. 인터널 테이블을 동적으로 생성하기 위해 CL_ABAP_TABLEDESCR=>CREATE 메소드를 호출하여 CL_ABAP_TABLEDESCR의 레퍼런스를 생성해야 합니다. 하지만 그전에 라인타입을 먼저 생성해야 하기 때문에 실제로는 CL_ABAP_STRUCTDESCR의 레퍼런스를 먼저 생성해야 합니다. 정리하자면 라인 타입에 해당하는 스트럭쳐 레퍼런스가 먼저 있어야 하고 그 라인타입으로 인터널테이블을 정의할 수 있습니다.

 

아래 예제는 MARA 타입으로 인터널테이블을 생성하는 예제 코드입니다.

TYPE-POOLS : abap .

 

*Step 1

DATA : lo_struct        TYPE REF TO cl_abap_structdescr ,

       lo_table         TYPE REF TO cl_abap_tabledescr  .

 

lo_struct ?= cl_abap_typedescr=>describe_by_name( 'MARA' ).

lo_table  = cl_abap_tabledescr=>create( lo_struct ) .

 

*Step 2

DATA : ref_dynamic_table TYPE REF TO data .

CREATE DATA ref_dynamic_table TYPE HANDLE lo_table .

 

*Step 3

FIELD-SYMBOLS : <fs_table> TYPE ANY TABLE.

ASSIGN ref_dynamic_table->* TO <fs_table> .

 

*Step 4

FIELD-SYMBOLS : <fs_struc> TYPE ANY .

 

LOOP AT  <fs_table> ASSIGNING <fs_struc> .

 

ENDLOOP.

 

 

스트럭쳐 레퍼런스를 가져오기 위해 cl_abap_typedescr=>describe_by_name( 'MARA' ) 구문을 사용하는 대신 cl_abap_structdescr=>create( struc_components ) 구문을 사용할 수도 있습니다. 앞서 본 예제에서 처럼 필드목록을 이용하여 동적으로 스트럭쳐를 구성하고 이것을 라인타입으로 지정하여 인터널테이블을 정의하는 것도 가능합니다. cl_abap_tabledescr=>create 메소드의 파라미터를 더 주면 SORTED 나 HASHED 종류를 지정할 수 있고 키필드 정의도 가능합니다.

 

끝.

이 기능은 NW ABAP 7.02 (= ECC 6.05) 부터 사용가능 합니다.

스탠다드 프로그램을 분석하다 보면 ABAP의 개발 방향이 Function Group 에서 Class 로 바뀌고 있다는 것을 많이 느끼게 됩니다.
class의 관계를 분석하는게 쉬운일이 아닌데요.
ABAP workbench에 UML로 표시해 주는 기능이 들어 있네요.
UML을 보면 분석에 많은 도움이 됩니다.


우선 SAP GUI 설치 프로그램으로 SAP JNet을 추가 설치 해야 합니다.
(이미 SAP GUI 설치할때 JNet을 설치 하셨으면 스킵)


서버에 들어가서 버전을 확인하세요.
이 기능은 NW ABAP 7.02 (= ECC 6.05) 부터 사용가능 합니다.


SE80의 왼쪽 트리부분에서 클래스를 선택하고,
마우스 오른쪽 버튼을 누르면 context-menu에서 Display - UML Class Diagram 을 선택합니다.



이렇게 아래와 같이 UML이 나타납니다.
이 화면에서 UML을 확인하면 됩니다.
좀 더 나아가서~
UML을 파일로 저장하고 평소에 사용하던 편리한 UML 툴로 보고 싶은 경우를 진행해 보겠습니다.
Execute Plug-In 버튼을 눌러서 파일로 저장하도록 합니다.


파일 저장을 선택합니다.

포맷은 XMI 1.1을 선택합니다.


저는 StarUML을 사용하고 있는데요. 여기서 불러오기 해보겠습니다.
StarUML을 실행하고 메뉴의 File - Import -XMI 를 선택합니다.


앞서 저장한 XMI 파일을 선택하고 진행합니다.
불러올 위치는 Design Model을 선택합니다.


처음에는 화면에 클래스가 보이지 않지만
model explorer에서 펼치고 클래스를 잡아서 main 창으로 던지면 UML 그림이 완성 됩니다.


끝.
아밥 프릭쇼 (http://enterprisegeeks.com/blog/tag/abap-freak-show/)
에서 ABAP 동영상 강좌를 보실수 있습니다. 영어입니다.

ABAP Freak Show – ABAP Tutorial Links

by Ed Herrmann on July 30, 2010 at 11:44 am

As many of the loyal egheads know, Thomas Jung has posted some great ABAP tutorials on the ABAP Freak Show. This post is a quick summary of some of these available tutorials to make it easier to watch later and pass around to all of your fellow ABAPers.

+ Recent posts