オブジェクト・イニシャライザー

初期設定関数は、インスタンスの属性とリンクを初期設定します。 イニシャライザーでは、オブジェクトに対してメモリーが (静的にあるいは動的に) 既に割り振られていると想定しています。 オブジェクト・イニシャライザーの名前のフォーマットは、<object>_Init() です。

例えば、次の例は、オブジェクト A のために生成されるイニシャライザーのプロトタイプです。

void A_Init(struct A_t* const me);

最初の引数は、初期設定されるオブジェクトへの定数ポインターです。 const キーワードは、ANSI C では定数ポインターを定義します。 定数ポインターを引数として渡すことにより、操作はポインターがアドレス指定しているオブジェクトの値を変更できますが、引数 me に含まれるアドレスの場合はできません。

オブジェクト・イニシャライザーには、以下に示す役割があり、これらを以下に示す順序で実行します。

  1. オブジェクトにサブオブジェクトがある場合は、サブオブジェクトのイニシャライザー関数を呼び出します。
  2. 関連の関係に対してリンクを設定します。
  3. コンストラクターの本体に入力されたユーザー・コードを実行します。 このコードには、オブジェクトのデータの初期設定が含まれている必要があります。
  4. 集約されたフレームワーク・オブジェクト (例えば、RiCTask オブジェクト、RiCReactive オブジェクト、および RiCMonitor オブジェクトなど) の初期設定をします。

サブオブジェクトの初期設定には、コンポジット・オブジェクトの各サブオブジェクト用のイニシャライザーの呼び出しが含まれます。 配列の場合、各サブオブジェクトの初期設定に $index キーワードを含むことができます。

デフォルトで、イニシャライザーには (me 引数以外の) 引数はありません。引数を使用するイニシャライザーを作成する場合、「オブジェクト」ウィンドウで引数の初期値を入力できます。 IBM® Rational® Rhapsody® は、「オブジェクト」ウィンドウで入力された値が入った引数を伴うイニシャライザーの初期設定コードを生成します。

サブオブジェクトの初期設定

コンポジションは、親のイニシャライザーでの initRelations() の呼び出しにより初期設定されます。 例えば、サブオブジェクト E を持つオブジェクト D に対して以下のイニシャライザーが生成されます。

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

D のイニシャライザー内の initRelations() 呼び出しにより、E のイニシャライザーが呼び出されます。

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

サブオブジェクトが配列として実装されている場合 (例えば、サブオブジェクトに 1 より大きい数値の多重度が指定されている場合)、このサブオブジェクトは、initRelations() 操作内で while() ループを使用して初期設定されます。 例えば、E の多重度が 2 であるとすると、E は、D 内部の 2 要素の配列として実装されます。次の 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++;
      }
   }
}

リンクの設定

関連したオブジェクトがコンポジット・オブジェクトのコンポーネントではない場合、 メインプログラムにより、(構成の「初期設定」タブで) オブジェクトの 1 つを初期インスタンスとして選択することでそれをインスタンス化させることができます。 そのオブジェクトのイニシャライザーで、関連したオブジェクトを明示的に作成して、次にそのオブジェクトへのリンクを設定できます。 例えば、オブジェクト A とオブジェクト B が関連していて、main() 関数が A を初期インスタンスとして初期設定する場合、A のイニシャライザーの本体に B へのリンクを設定するための次のコードを作成することができます。

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

to-many 関係へのリンクの設定には、コンテナーのイニシャライザーの呼び出しが必要です。 次のコードでは、RiCCollection_Init() への呼び出しにより Furnace から 3 つの itsRooms へのリンクが設定されます。 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() の呼び出しは、 アニメーションを有効にした場合に生成されるトレース/アニメーション設定マクロです。1 つ目のマクロは、イニシャライザーが呼び出された時にアニメーターに通知し、アニメーション・インスタンスを作成します。 2 番目のマクロはイニシャライザーが直に終了するという時にアニメーターに通知します。

ユーザー初期設定コードの実行

コンストラクター用に入力されたユーザー・コードには、オブジェクトの属性の初期設定が含まれます。 オブジェクト・コンストラクターの各パラメーターに実際の値を指定することができます。 実際の値は、未解釈テキストとして逐語的に挿入されます。

ユーザー・コードは、コード内の /*#[ 記号と /*#] 記号の間に生成されます。 例えば、イニシャライザーの「実装」フィールドに以下のコードを入力できます。

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);
}

フィードバック