오브젝트 초기자(initializer)

초기화 함수는 인스턴스의 속성과 링크를 초기화합니다. 초기자(initializer)는 이전에 오브젝트에 메모리가 할당된(정적으로 또는 동적으로) 것으로 가정합니다. 오브젝트 초기자(initializer) 이름의 형식은 <object>_Init()입니다.

예를 들어, 다음 예제는 오브젝트 A에 대해 생성되는 초기자(initializer)의 프로토타입입니다.

void A_Init(struct A_t* const me);

첫 번째 인수는 초기화 중인 오브젝트에 대한 상수 포인터입니다. const 키워드는 ANSI C에서 상수 포인터를 정의합니다. 상수 포인터를 인수로 전달하면 오퍼레이션이 me 인수에 있는 주소가 아니라 포인터가 주소 지정하는 오브젝트의 값을 변경할 수 있습니다.

오브젝트 초기자(initializer)에는 다음과 같은 책임이 있으며, 다음 순서로 수행합니다.

  1. 오브젝트에 서브오브젝트가 있는 경우 서브오브젝트 초기자(initializer) 함수를 호출합니다.
  2. 연관 관계에 대한 링크를 설정합니다.
  3. 생성자의 본문으로 입력한 사용자 코드를 실행합니다. 이 코드에는 오브젝트에 대한 데이터의 초기화가 포함되어야 합니다.
  4. 집계된 프레임워크 오브젝트(예: RiCTask, RiCReactiveRiCMonitor 오브젝트)를 초기화합니다.

서브오브젝트 초기화에는 컴포지트 오브젝트의 각 서브오브젝트에 대한 초기자(initializer) 호출이 포함됩니다. 배열의 경우 각 서브오브젝트의 초기화에는 $index 키워드가 포함될 수 있습니다.

기본적으로 초기자(initializer)에는 (me 인수가 아닌 다른) 인수가 없습니다. 인수가 있는 초기자(initializer)를 작성하는 경우 오브젝트 창에서 인수에 대한 초기값을 입력할 수 있습니다. IBM® Rational® Rhapsody®는 오브젝트 창에 입력된 값에서 인수가 있는 초기자(initializer)에 대한 초기화 코드를 생성합니다.

서브오브젝트 초기화

컴포지션은 상위의 초기자(initializer)에서 initRelations()를 호출하여 초기화됩니다. 예를 들어, E 서브오브젝트가 있는 D 오브젝트에 대해 다음 초기자(initializer)가 생성됩니다.

void D_Init(D* const me) {
   initRelations(me);
}

D 초기자(initializer)의 initRelations() 호출은 E에 대한 초기자(initializer)를 호출합니다.

static void initRelations(D* const me) {
    E_Init(&me->E);
}

서브오브젝트가 배열로 구현되는 경우(예를 들어, 서브오브젝트에 1보다 큰 숫자 다중성을 가지고 있어서) 서브오브젝트는 initRelations() 오퍼레이션에서 while() 루프를 사용하여 초기화됩니다. 예를 들어, E의 다중성이 2인 경우 ED에서 두 요소 배열로 구현됩니다. 다음 while() 루프 예제는 E의 두 인스턴스 모두를 초기화하기 위해 DinitRelations() 오퍼레이션에서 생성됩니다.

static void initRelations(D* const me) {
   E_Init(&(me->E));
   {
      RhpInteger iter = 0;
      while (iter < 5){
         E_Init(&((me->itsE)[iter]));
         iter++;
      }
   }
}

링크 설정

관련 오브젝트가 컴포지트 오브젝트의 컴포넌트가 아닌 경우 오브젝트 중 하나를 초기 인스턴스로 선택하여 기본 프로그램이 그 오브젝트를 인스턴스화하도록 할 수 있습니다(구성의 초기화 탭에서). 오브젝트에 대한 해당 초기자(initializer)에서 관련 오브젝트를 명시적으로 작성한 후 이 오브젝트에 링크를 설정할 수 있습니다. 예를 들어, 오브젝트 A 및 오브젝트 B가 관련되고 main() 함수가 A를 초기 인스턴스로 인스턴스화하는 경우 A의 초기자(initializer) 본문에서 다음 코드를 작성하여 B에 대한 링크를 설정할 수 있습니다.

B *itsB = B_Create();
A_setItsB(me, itsB);

많은 관련 오브젝트에 대해 하나의 링크를 설정하는 데는 컨테이너에 대한 초기자(initializer) 호출이 포함됩니다. 다음 코드에서 RiCCollection_Init() 호출은 세 개의 itsRooms에 대한 Furnace의 링크를 설정합니다. RiCTRUE 값을 RiCCollection_setFixedSize()로 전달하는 것은 콜렉션이 고정 크기임을 알립니다.

void Furnace_Init(Furnace* const me, RiCTask * p_task) {
    RiCReactive_init(&me->ric_reactive, (void*)me, 
        p_task, &Furnace_reactiveVtbl);
    RiCCollection_Init(&me->itsRoom, 3);
    NOTIFY_REACTIVE_CONSTRUCTOR(me, NULL, Furnace,
        Furnace, Furnace(), 0, Furnace_SERIALIZE);
    {
        RiCCollection_setFixedSize(&me->itsRoom,
            RiCTRUE);
    }
    initStatechart(me);
    NOTIFY_END_CONSTRUCTOR(me);
}

NOTIFY_CONSTRUCTOR()NOTIFY_END_CONSTRUCTOR() 호출은 애니메이션이 사용될 때 생성된 인스트루먼테이션 매크로입니다. 첫 번째 매크로는 초기자(initializer)가 호출되어 애니메이션 인스턴스를 작성할 때 애니메이터에게 알립니다. 두 번째 매크로는 초기자(initializer)가 종료하려고 할 때 애니메이터에게 알립니다.

사용자 초기화 코드 실행

생성자에 대해 입력한 사용자 코드에는 오브젝트 속성의 초기화가 포함됩니다. 오브젝트 생성자에서 모든 매개변수에 대한 실제 값을 지정할 수 있습니다. 실제 값은 해석되지 않은 텍스트로 삽입된 verbatim입니다.

사용자 코드는 코드에서 /*#[/*#] 기호 사이에 생성됩니다. 예를 들어, 초기자(initializer)에 대한 구현 필드에서 다음 코드를 입력할 수 있습니다.

RiCString temp;
RiCString_Init(&temp, "Hello World");
A_print(me, temp);

이 코드는 다음과 같이 구현됩니다.

void A_Init(struct A_t* const me) {
    NOTIFY_CONSTRUCTOR(me, NULL, A, A, A(), 0,
        A_SERIALIZE);
    me->itsB = NULL;
    {
        /*#[ operation A() */
        RiCString temp;
        RiCString_Init(&temp, "Hello World");
        A_print(me, temp);
        /*#]*/
    }
    NOTIFY_END_CONSTRUCTOR(me);
}

피드백