클래스 인스턴스 생성

Objective

After completing this lesson, you will be able to aBAP 클래스의 인스턴스를 생성합니다.

인스턴스 생성

동일한 유형의 일반 변수와 같은 특성을 사용합니다. 그러나 클래스 외부에서는 특성 이름으로는 특성을 명확하게 식별할 수 없습니다. 클래스 외부에서 정적 특성을 처리하려면 먼저 클래스 이름을 입력한 다음 정적 컴포넌트 선택자(=>)를 입력한 다음 특성 이름만 지정합니다. 정적 컴포넌트 선택자는 등호 및 보다 큼 부호로 구성된 이중 화살표입니다.

힌트

컴포넌트 선택 전후에 공백을 사용할 수 없습니다.

예를 들어 특성의 경우 상황이 훨씬 더 복잡합니다. 인스턴스 컴포넌트에 액세스하려면 참조 변수가 필요합니다.

참조 변수는 오브젝트를 생성, 처리, 관리하는 데 사용하는 특별한 종류의 변수입니다. 참조 변수는 프로그램 메모리의 클래스 인스턴스를 가리키는 데 사용됩니다. DATA 문을 사용하고 클래스 이름 뒤에 TYPE REF TO를 추가하여 참조 변수를 선언합니다.

참조 변수의 초기 값을 NULL 참조라고 합니다. 참조는 아직 아무 것도 가리키지 않습니다.

클래스의 신규 인스턴스를 생성하려면 NEW 연산자를 사용합니다. 위의 예에서는 값 할당 오른쪽에 NEW #( ) 식을 사용합니다. 표현식의 결과는 새로 생성된 인스턴스의 메모리 주소입니다. 그러면 이 참조가 지정의 왼쪽에 있는 참조 변수에 저장됩니다.

표현식에는 인스턴스화하려는 클래스 이름이 표시되지 않습니다. 그러나 NEW #( ) 식의 위치에서 대상 변수 연결의 유형이 REF TO lcl_connection임을 이미 알고 있으므로 lcl_connection 클래스의 인스턴스를 생성해야 한다는 것을 알고 있습니다. NEW 연산자 뒤의 파운드 기호(#)는 "등호 앞에 변수 유형 사용"을 의미합니다. (고급 시나리오에서는 파운드 기호 자리에 클래스 이름을 실제로 지정할 수 있습니다.)

힌트

괄호 사이에는 공백이 하나 이상 있어야 합니다.

클래스를 처음으로 처리하는 경우(정적 컴포넌트에 액세스하거나 클래스의 인스턴스를 생성할 수 있음) 런타임 시스템에서 클래스 정의도 프로그램 메모리에 로드합니다. 이 클래스 정의에는 각 인스턴스에 대해 한 번만 존재하는 모든 정적 특성이 클래스에 한 번만 포함됩니다.

클래스 이름과 정적 컴포넌트 선택기를 사용하여 정적 컴포넌트를 처리합니다. 액세스할 인스턴스를 지정해야 하기 때문에 인스턴스 컴포넌트에서는 작동하지 않습니다.

클래스 외부에서 인스턴스 특성을 처리하려면 먼저 참조 변수를 입력한 다음 인스턴스 컴포넌트 선택자(->)를 입력한 다음 특성 이름만 지정합니다. 인스턴스 컴포넌트 선택자는 대시와 보다 큼 부호로 구성된 화살표입니다.

노트

다른 많은 프로그래밍 언어와 달리 ABAP에서는 인스턴스 컴포넌트 선택기와 정적 컴포넌트 선택기에 서로 다른 문자를 사용합니다.

오브젝트 지향 프로그래밍의 주요 특징 중 하나는 동일한 클래스의 여러 인스턴스를 생성할 수 있다는 점입니다. 각 인스턴스는 프로그램 메모리의 다른 위치에 생성되며 한 인스턴스의 인스턴스 특성 값은 다른 인스턴스의 값과 독립적입니다. 그러나 그림에서 볼 수 있듯이 동일한 클래스의 인스턴스는 정적 특성 값을 공유합니다.

하나의 참조 변수를 다른 참조 변수에 지정하면 시스템에서 첫 번째 변수가 가리키는 오브젝트의 주소를 두 번째 참조 변수에 복사합니다. 결과적으로 두 개의 참조 변수가 동일한 오브젝트를 가리키게 됩니다.

동일한 참조 변수를 사용하여 클래스의 인스턴스를 여러 개 생성할 수 있습니다. NEW #( ) 표현식을 사용할 때마다 클래스의 신규 인스턴스가 생성되고 신규 인스턴스의 주소가 참조 변수에 배치됩니다. 그러나 신규 인스턴스의 주소는 이전 인스턴스의 주소를 덮어씁니다.

위의 예에서 lcl_connection (2)의 주소는 lcl_connection (1)의 주소를 덮어씁니다. 따라서 프로그램에 lcl_connection (1)을 가리키는 참조 변수가 더 이상 없습니다. 인스턴스에 이러한 일이 발생하면 프로그램에서 이 인스턴스가 더 이상 처리될 수 없습니다.

런타임 시스템에는 프로그램 메모리가 더 이상 처리될 수 없는 인스턴스로 채워지고 그에 따라 오버플로우가 발생하는 것을 방지하기 위한 가비지 컬렉터(garbage collector)라는 컴포넌트가 있습니다. 가비지 컬렉터는 참조에서 더 이상 가리키지 않는 오브젝트를 찾고 파기하기 위해 정기적으로 실행되는 프로그램입니다. 프로그램 실행 중에 덮어쓰거나 CLEAR 문을 사용하여 오브젝트에 대한 마지막 참조를 삭제하면 다음 번에 가비지 컬렉터가 실행될 때 해당 오브젝트가 파기됩니다.

노트

프로그램이 끝날 때 모든 참조 변수가 해제되면 가비지 수집기가 지적한 모든 인스턴스를 파기합니다. 프로그램에서 자원 관리에 대해 걱정할 필요가 없습니다.

ABAP 클래스의 인스턴스 생성 방법

내부 테이블의 인스턴스 관리

오브젝트를 활성 상태로 유지할 수 있는 방법 중 하나는 내부 테이블에 참조 변수를 저장하는 것입니다. 이는 오브젝트의 전체 시리즈를 생성하는 경우에 사용되는 기법입니다. 이렇게 하면 단일 참조 변수로 여러 개의 오브젝트를 생성할 수 있습니다. 참조 변수를 다음 오브젝트의 주소로 덮어쓰더라도 내부 테이블에는 참조 변수가 포함되어 있으므로 기존 오브젝트는 안전합니다. 따라서 오브젝트에 대한 "마지막" 참조는 절대 삭제되지 않습니다.

내부 테이블에서 인스턴스를 관리하는 방법

인스턴스 생성 및 관리

이 연습문제에서는 로컬 클래스의 인스턴스를 생성하고 관리합니다.

템플릿:

  • /LRN/CL_S4D400_CLS_LOCAL_CLASS(전역 클래스)

솔루션:

  • /LRN/CL_S4D400_CLS_INSTANCES(전역 클래스)

태스크 1: 템플릿 복사(선택사항)

템플릿 클래스를 복사합니다. 이전 연습문제를 완료한 경우 이 태스크를 건너뛰고 클래스 ZCL_##_LOCAL_CLASS 를 계속 편집할 수 있습니다.

단계

  1. ABAP 편집기에서 전역 클래스 /LRN/CL_S4D400_CLS_LOCAL_CLASS 의 소스 코드를 엽니다.

    1. Eclipse 툴바에서 Open ABAP Development Object 를 선택합니다. 또는 Ctrl + Shift + A 를 눌러도 됩니다.

    2. 검색 문자열로 /LRN/CL_S4D400_CLS 를 입력합니다.

    3. 개발 오브젝트 리스트에서 /LRN/CL_S4D400_CLS_LOCAL_CLASS 를 선택하고 확인 을 선택합니다.

  2. 프로젝트 탐색기 뷰를 편집기와 연결합니다.

    1. 프로젝트 탐색기 툴바에서 편집기가 있는 링크 버튼을 찾습니다. 아직 누르지 않은 경우 선택합니다. 따라서 편집기에서 열려 있는 개발 오브젝트가 프로젝트 탐색기에서 강조표시되어야 합니다.

  3. 클래스 /LRN/CL_S4D400_CLS_LOCAL_CLASS 를 사용자의 패키지에 포함된 클래스에 복사합니다(제안 이름: ZCL_##_INSTANCES, ##은 그룹 번호).

    1. 프로젝트 탐색기 뷰에서 클래스 /LRN/CL_S4D400_CLS_LOCAL_CLASS 를 마우스 오른쪽 버튼으로 클릭하여 컨텐트 메뉴를 엽니다.

    2. 단축 메뉴에서 Duplicate .... 를 선택합니다.

    3. 패키지 필드에 패키지 이름을 입력합니다. 이름 필드에 이름 ZCL_##_INSTANCES 를 입력합니다. 여기서 ##은 그룹 번호입니다.

    4. 내역을 조정하고 다음 을 선택합니다.

    5. 전송 요청을 확인하고 Finish를 선택합니다.

태스크 2: 인스턴스 생성

전역 클래스의 주요 메소드에서 참조 변수를 선언하고 로컬 클래스의 인스턴스를 생성합니다.

단계

  1. 전역 클래스의 if_oo_adt_classrun~main 메소드에서 참조 변수(제안 이름: 연결)를 선언하고 로컬 클래스 lcl_connection으로 유형을 지정합니다.

    1. 전역 클래스 탭으로 전환합니다.

    2. 코드를 다음과 같이 조정합니다.

      Code Snippet
      1234567
      METHOD if_oo_adt_classrun~main. DATA connection TYPE REF TO lcl_connection. ENDMETHOD.
  2. 클래스의 인스턴스를 생성하고 carrier_idconnection_id 특성을 설정합니다(권장 값: 특성 carrier_id경우 LH, connection_id 특성의 경우 0400).

    1. 코드를 다음과 같이 조정합니다.

      Code Snippet
      12345678
      DATA connection TYPE REF TO lcl_connection. connection = new #( ). connection->carrier_id = 'LH'. connection->connection_id = '0400'.

      힌트

      컴포넌트 선택(->)을 입력한 후 Strg + Space 를 눌러 제안 리스트에서 특성 이름을 선택합니다.
  3. 클래스를 활성화하고 디버거를 사용하여 발생하는 작업을 단계별로 분석합니다.

    1. Ctrl + F3 을 눌러 클래스를 활성화합니다.

    2. connection = new #( ). 라인 옆에 있는 편집기의 왼쪽 여백을 두 번 클릭하여 중단점을 설정합니다.

    3. F9 를 눌러 클래스를 실행합니다.

    4. 단어 연결을 두 번 클릭하여 참조 변수 연결의 내용을 표시합니다.

    5. F5 를 눌러 디버거에서 한 단계 더 진행합니다. 연결 값이 변경되었는지 확인합니다.

    6. Variables 뷰에서 분기 연결을 펼쳐서 클래스의 초기 특성을 조회합니다.

    7. F5 를 눌러 디버거에서 한 단계 더 진행합니다. carrier_id 의 값이 변경되었는지 확인합니다.

    8. F5 를 다시 누릅니다. Connection_ID 값이 변경되었는지 확인합니다.

태스크 3: 여러 인스턴스 관리

로컬 클래스의 인스턴스를 추가로 생성하고 이러한 인스턴스에 대한 참조를 내부 테이블에 저장합니다.

단계

  1. 전역 클래스의 if_oo_adt_classrun~main( ) 메소드에서 라인 유형이 REF TO lcl_connection 인 내부 테이블(권장 이름: connections)을 선언합니다.

    1. 코드를 다음과 같이 조정합니다.

      Code Snippet
      123456789
      DATA connection TYPE REF TO lcl_connection. DATA connections TYPE TABLE OF REF TO lcl_connection. connection = new #( ). connection->carrier_id = 'LH'. connection->connection_id = '0400'.
  2. 클래스를 인스턴스화하고 특성을 설정한 후 내부 테이블에 오브젝트 참조를 추가합니다.

    1. 코드를 다음과 같이 조정합니다.

      Code Snippet
      123456789
      connection = NEW #( ). connection->carrier_id = 'LH'. connection->connection_id = '0400'. APPEND connection TO connections.
  3. lcl_connection 클래스의 인스턴스를 두 개 더 생성하고 인스턴스 특성을 첫 번째 인스턴스와는 다른 값으로 설정한 다음 내부 테이블 연결에 신규 인스턴스에 참조를 추가합니다. 세 인스턴스 모두에 동일한 참조 변수 연결을 사용합니다.

    1. 코드를 다음과 같이 조정합니다.

      Code Snippet
      12345678910111213141516171819202122
      connection = NEW #( ). connection->carrier_id = 'LH'. connection->connection_id = '0400'. APPEND connection TO connections. connection = NEW #( ). connection->carrier_id = 'AA'. connection->connection_id = '0017'. APPEND connection TO connections. connection = NEW #( ). connection->carrier_id = 'SQ'. connection->connection_id = '0001'. APPEND connection TO connections.
  4. 클래스를 활성화하고 디버거를 사용하여 발생하는 작업을 단계별로 분석합니다.

    1. Ctrl + F3 을 눌러 클래스를 활성화합니다.

    2. 첫 번째 라인 connection = new #( ).옆에 있는 편집기의 왼쪽 여백을 더블 클릭하여 중단점을 제거합니다.

    3. 첫 번째 라인 APPEND connection TO connections.옆에 있는 편집기의 왼쪽 여백을 두 번 클릭하여 새 중단점을 설정합니다.

    4. F9 를 눌러 클래스를 실행합니다.

    5. 단어 연결을 두 번 클릭하여 참조 변수 연결의 내용을 표시합니다.

    6. 단어 connections 를 더블 클릭하여 내부 테이블 연결의 내용을 표시합니다.

    7. F5 를 눌러 디버거에서 한 단계 더 진행합니다. 연결 내용이 변경되었는지 확인합니다.

    8. 변수 뷰에서 분기 연결을 펼쳐서 내부 테이블(Internal Table)의 내용을 조회합니다.

    9. F5 를 프로그램 끝에 도달할 때까지 여러 번 누릅니다. 내부 테이블(Internal Table)의 내용을 확인합니다.

    10. 전역 클래스 탭의 코드를 모델 솔루션에서 추출한 다음 코드와 비교합니다.

      Code Snippet
      123456789101112131415161718192021222324252627282930313233343536
      METHOD if_oo_adt_classrun~main. DATA connection TYPE REF TO lcl_connection. DATA connections TYPE TABLE OF REF TO lcl_connection. * First Instance ********************************************************************** connection = NEW #( ). connection->carrier_id = 'LH'. connection->connection_id = '0400'. APPEND connection TO connections. * Second Instance ********************************************************************** connection = NEW #( ). connection->carrier_id = 'AA'. connection->connection_id = '0017'. APPEND connection TO connections. * Third Instance ********************************************************************** connection = NEW #( ). connection->carrier_id = 'SQ'. connection->connection_id = '0001'. APPEND connection TO connections. ENDMETHOD.