
Iterator를 사용해서 구현과는 분리하여 하나 하나 요소들을 셀 수 있다.
아래 소스를 보면 loop를 돌 때 Iterator의 메소드만 이용하고 있으며 Aggregate 클래스가 어떤 식으로 구현되어 있는가 – 배열이든, 벡터든, Internal Table이든 – 는 상관없다. 즉 나중에 Aggregate의 요소 관리 방식을 얼마든지 바꿀 수 있다는 이야기.
이를 위해 아래와 같은 것들이 필요하다.
- Iterator 인터페이스.
- Aggregate 인터페이스. Iterator 인터페이스 타입의 객체를 리턴하는 메소드를 제공.
- ConcreteIterator. Iterator 인터페이스를 구현한다. 구체적으로 어떤 놈을 어떻게 돌아야하는지 알고 있어야 하기 때문에 ConcreteAggregate의 객체를 내부에 가지고 있다.
- ConcreteAggregate. Aggregate 인터페이스를 구현한다. 자신을 인자로 넘겨주면서 ConcreteIterator를 생성한다.
헷갈리기 쉬운게 Next()와 hasNext()인데,
- Next() 호출시 현재 요소를 리턴하면서 내부적으로 다음 위치로 이동하게 된다.
- hasNext()는 최후의 요소를 얻기 전에는 true를 리턴하고 최후의 요소를 얻은 후에는 false를 리턴한다. 다음에 Next()를 호출해도 괜찮은지 조사하는 메소드로 이해하면 된다.
아래는 해당 소스.
*&---------------------------------------------------------------------*
*& Report ZP_ITERATOR
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT zp_iterator.
*PARAMETERS:
*----------------------------------------------------------------------*
* INTERFACE lif_iterator
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE lif_iterator.
TYPE-POOLS abap.
METHODS: has_next RETURNING value(r_flag) TYPE abap_bool,
next RETURNING VALUE(r_obj) TYPE REF TO object.
ENDINTERFACE. "lif_iterator
*----------------------------------------------------------------------*
* INTERFACE lif_aggregate
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
INTERFACE lif_aggregate.
METHODS iterator RETURNING VALUE(r_it) TYPE REF TO lif_iterator.
ENDINTERFACE. "lif_aggregate
*----------------------------------------------------------------------*
* CLASS lcl_book DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_book DEFINITION.
PUBLIC SECTION.
METHODS: constructor IMPORTING i_name TYPE string,
get_name RETURNING value(r_name) TYPE string.
PRIVATE SECTION.
DATA m_name TYPE string.
ENDCLASS. "lcl_book DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_bookshelf DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bookshelf DEFINITION.
PUBLIC SECTION.
INTERFACES lif_aggregate.
METHODS: get_book_at IMPORTING i_idx TYPE i
RETURNING VALUE(r_book) TYPE REF TO lcl_book,
append_book IMPORTING i_book TYPE REF TO lcl_book,
get_length RETURNING value(r_last) TYPE i.
PRIVATE SECTION.
DATA: m_books TYPE STANDARD TABLE OF REF TO lcl_book,
m_last TYPE i.
ENDCLASS. "lcl_bookshelf DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_bookshelf_it DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bookshelf_it DEFINITION.
PUBLIC SECTION.
INTERFACES lif_iterator.
METHODS constructor IMPORTING i_bookshelf TYPE REF TO lcl_bookshelf.
PRIVATE SECTION.
DATA: m_bookshelf TYPE REF TO lcl_bookshelf,
m_idx TYPE i VALUE 1.
ENDCLASS. "lcl_bookshelf_it DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_book IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_book IMPLEMENTATION.
METHOD constructor.
m_name = i_name.
ENDMETHOD. "constructor
METHOD get_name.
r_name = m_name.
ENDMETHOD. "get_name
ENDCLASS. "lcl_book IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS lcl_bookshelf IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bookshelf IMPLEMENTATION.
METHOD get_book_at.
READ TABLE m_books INDEX i_idx INTO r_book.
ENDMETHOD. "get_book_at
METHOD append_book.
APPEND i_book TO m_books.
ENDMETHOD. "append_book
METHOD get_length.
r_last = lines( m_books ).
ENDMETHOD. "get_length
METHOD lif_aggregate~iterator.
CREATE OBJECT r_it TYPE lcl_bookshelf_it EXPORTING i_bookshelf = me.
ENDMETHOD. "lif_aggregate~iterator
ENDCLASS. "lcl_bookshelf IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS lcl_bookshelf_it IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_bookshelf_it IMPLEMENTATION.
METHOD constructor.
m_bookshelf = i_bookshelf.
ENDMETHOD. "constructor
METHOD lif_iterator~has_next.
IF m_idx <= m_bookshelf->get_length( ).
r_flag = abap_true.
ELSE.
r_flag = abap_false.
ENDIF.
ENDMETHOD. "lif_iterator~has_next
METHOD lif_iterator~next.
r_obj = m_bookshelf->get_book_at( m_idx ).
ADD 1 TO m_idx.
ENDMETHOD. "lif_iterator~next
ENDCLASS. "lcl_bookshelf_it IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS demo DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS demo DEFINITION.
PUBLIC SECTION.
CLASS-METHODS: main.
ENDCLASS. "demo DEFINITION
*----------------------------------------------------------------------*
* CLASS demo IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS demo IMPLEMENTATION.
METHOD main.
DATA: lr_bookshelf TYPE REF TO lcl_bookshelf,
lr_book_1 TYPE REF TO lcl_book,
lr_book_2 TYPE REF TO lcl_book,
lr_book_3 TYPE REF TO lcl_book,
lr_book_4 TYPE REF TO lcl_book,
lr_book_5 TYPE REF TO lcl_book,
lr_it TYPE REF TO lif_iterator,
lr_book TYPE REF TO lcl_book,
lv_str TYPE string.
CREATE OBJECT: lr_bookshelf,
lr_book_1 EXPORTING i_name = 'Around the world in 80 days',
lr_book_2 EXPORTING i_name = 'Bible',
lr_book_3 EXPORTING i_name = 'The Lord of the Rings',
lr_book_4 EXPORTING i_name = 'Jonathan Livingston Seagull',
lr_book_5 EXPORTING i_name = 'The Keys of the Kingdom'.
lr_bookshelf->append_book( lr_book_1 ).
lr_bookshelf->append_book( lr_book_2 ).
lr_bookshelf->append_book( lr_book_3 ).
lr_bookshelf->append_book( lr_book_4 ).
lr_bookshelf->append_book( lr_book_5 ).
lr_it = lr_bookshelf->lif_aggregate~iterator( ).
WHILE lr_it->has_next( ) = abap_true.
lr_book ?= lr_it->next( ).
lv_str = lr_book->get_name( ).
WRITE: / lv_str.
ENDWHILE.
ENDMETHOD. "main
ENDCLASS. "demo IMPLEMENTATION
START-OF-SELECTION.
demo=>main( ).
Post a Comment