NaturalX アプリケーションの開発

このドキュメントでは、クラスを定義および使用してアプリケーションを開発する方法について説明します。

以下のトピックについて説明します。


開発環境

  • Windows プラットフォームでのクラスの開発
    Windows プラットフォームでは、Natural クラスを開発するためのツールとして、Natural からクラスビルダが提供されます。クラスビルダは、構造化された階層順に Natural クラスを表示し、ユーザーがクラスとそのコンポーネントを効率的に管理できるようにします。クラスビルダを使用すると、この後で説明する構文要素に関する知識はまったく必要ないか、または基礎知識だけで済みます。

  • SPoD を使用したクラスの作成
    メインフレーム、UNIX、または OpenVMS の一部またはすべてのリモート開発サーバーが含まれる Natural Single Point of Development(SPoD)環境では、Natural スタジオのフロントエンドで使用可能なクラスビルダを使用して、メインフレーム、UNIX、または OpenVMS プラットフォーム上でクラスを開発できます。この場合、この後で説明する構文要素に関する知識はまったく必要ないか、または基礎知識だけで済みます。

  • メインフレーム、UNIX、または OpenVMS プラットフォームでのクラスの開発
    SPoD を使用しない場合は、Natural プログラムエディタを使ってこれらのプラットフォームのクラスを開発することができます。この場合は、この後で説明するクラス定義の構文の知識が必要です。

クラスの定義

クラスを定義するときは、Natural クラスモジュールを作成する必要があります。この中で DEFINE CLASS ステートメントを作成します。DEFINE CLASS ステートメントを使用して、外部的に使用可能な名前をクラスに割り当て、そのインターフェイス、メソッドおよびプロパティを定義します。クラスのインスタンスのレイアウトを記述するオブジェクトデータエリアをクラスに割り当てることもできます。

このセクションでは、次のトピックについて説明します。

Natural クラスモジュールの作成

Start of instruction setNatural クラスモジュールを作成するには

  • CREATE OBJECT ステートメントを使用して、クラスタイプの Natural オブジェクトを作成します。

クラスの指定

DEFINE CLASS ステートメントは、クラスの名前、クラスがサポートするインターフェイス、およびそのオブジェクトの構造を定義します。

Start of instruction setクラスを指定するには

  • DEFINE CLASS ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。

インターフェイスの定義

クラスの各インターフェイスは、クラス定義内部の INTERFACE ステートメントで指定されます。INTERFACE ステートメントは、インターフェイスの名前と多数のプロパティおよびメソッドを指定します。COM クラスとして登録されるクラスについては、インターフェイスのグローバルユニーク ID も指定されます。

クラスには 1 つ以上のインターフェイスを定義できます。インターフェイスごとに 1 つの INTERFACE ステートメントがクラス定義に指定されます。各 INTERFACE ステートメントには 1 つ以上の PROPERTY 節および METHOD 節が含まれます。通常、1 つのインターフェイスに含まれるプロパティとメソッドは、技術またはビジネスのいずれかの観点から関連付けられます。

PROPERTY 節はプロパティの名前を定義し、オブジェクトデータエリアからプロパティに変数を割り当てます。この変数を使用して、プロパティの値を保存します。

METHOD 節はメソッドの名前を定義し、メソッドにサブプログラムを割り当てます。このサブプログラムを使用して、メソッドを実装します。

Start of instruction setインターフェイスを定義するには

  • INTERFACE ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。

オブジェクトデータ変数のプロパティへの割り当て

PROPERTY ステートメントは、複数のクラスが同じインターフェイスを異なる方法で実装するときにのみ使用されます。この場合、クラスは同じインターフェイス定義を共有し、Natural コピーコードからインクルードします。次に PROPERTY ステートメントを使用して、インターフェイス定義のでオブジェクトデータエリアからプロパティに変数を割り当てます。INTERFACE ステートメントの PROPERTY 節と同様に、PROPERTY ステートメントはプロパティの名前を定義し、オブジェクトデータエリアからプロパティに変数を割り当てます。この変数を使用して、プロパティの値を保存します。

Start of instruction setオブジェクトデータ変数をプロパティに割り当てるには

  • PROPERTY ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。

サブプログラムのメソッドへの割り当て

METHOD ステートメントは、複数のクラスが同じインターフェイスを異なる方法で実装するときにのみ使用されます。この場合、クラスは同じインターフェイス定義を共有し、Natural コピーコードからインクルードします。METHOD ステートメントは、インターフェイス定義のでサブプログラムをメソッドに割り当てるために使用されます。INTERFACE ステートメントの METHOD 節と同様に、METHOD ステートメントはメソッドの名前を定義し、サブプログラムをメソッドに割り当てます。このサブプログラムを使用して、メソッドを実装します。

Start of instruction setサブプログラムをメソッドに割り当てるには

  • METHOD ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。

メソッドの実装

メソッドは次のような一般形式の Natural サブプログラムとして実装されます。

DEFINE DATA statement
*
* Implementation code of the method
*
END

DEFINE DATA ステートメントの詳細については、『ステートメント』ドキュメントを参照してください。

DEFINE DATA ステートメントのすべての節はオプションです。

データの整合性を確保するために、インラインデータ定義ではなくデータエリアを使うことをお勧めします。

PARAMETER 節を指定すると、メソッドにパラメータや戻り値を指定することができます。

パラメータデータエリアの BY VALUE とマークされたパラメータは、メソッドの入力パラメータです。

BY VALUE とマークされていないパラメータは、"参照によって"渡される入力/出力パラメータです。これがデフォルトです。

BY VALUE RESULT とマークされている最初のパラメータが、メソッドの戻り値として返されます。複数のパラメータがこのようにマークされている場合は、その他のパラメータは入力/出力パラメータとして扱われます。

OPTIONAL とマークされたパラメータは、メソッドが呼び出される場合は指定する必要はありません。SEND METHOD ステートメントで nX 表記を使用することにより、これらを未指定にしておくことができます。

メソッドサブプログラムが、クラス定義内の対応する METHOD ステートメントに指定されたものとまったく同じパラメータを受け入れるようにするには、インラインデータ定義ではなくパラメータデータエリアを使用します。対応する METHOD ステートメント内のものと同じパラメータデータエリアを使用します。

メソッドサブプログラムでオブジェクトデータ構造にアクセスするために、OBJECT 節を指定できます。メソッドサブプログラムがオブジェクトデータに正しくアクセスできるようにするには、インラインデータ定義ではなくローカルデータエリアを使用します。DEFINE CLASS ステートメントの OBJECT 節に指定されているものと同じローカルデータエリアを使用してください。

GLOBAL 節、LOCAL 節、および INDEPENDENT 節は、他の任意の Natural プログラムで使用できます。

技術的には可能ですが、通常はメソッドサブプログラムで CONTEXT 節を使用することは意味がありません。

次の例は、特定の人物に関するデータをテーブルから検索します。検索キーは BY VALUE パラメータとして渡されます。結果のデータは、"BY REFERENCE" パラメータで返されます。"BY REFERENCE" はデフォルト定義です。メソッドの戻り値は BY VALUE RESULT 指定によって定義されます。

Example

クラスとオブジェクトの使用

ローカルの Natural セッションで作成されたオブジェクトは、同じ Natural セッションの他のモジュールからアクセスできます。

CREATE OBJECT ステートメントは、特定のクラスのオブジェクト(インスタンスとも呼ばれます)を作成するために使用します。

Natural プログラムのオブジェクトを参照するには、オブジェクトハンドルを DEFINE DATA ステートメントで定義する必要があります。オブジェクトのメソッドは SEND METHOD ステートメントで呼び出されます。オブジェクトにはプロパティを指定できます。プロパティには通常の割り当て構文を使用してアクセスできます。

次の手順について説明します。

オブジェクトハンドルの定義

Natural プログラムのオブジェクトを参照するには、オブジェクトハンドルを DEFINE DATA ステートメントで次のように定義する必要があります。

DEFINE DATA
 level-handle-name [(array-definition)] HANDLE OF OBJECT
 ...
END-DEFINE

例:

DEFINE DATA LOCAL
1 #MYOBJ1 HANDLE OF OBJECT
1 #MYOBJ2 (1:5) HANDLE OF OBJECT
END-DEFINE

クラスのインスタンスの作成

Start of instruction setクラスのインスタンスを作成するには

  • CREATE OBJECT ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。

オブジェクトの特定メソッドの呼び出し

Start of instruction setオブジェクトの特定メソッドを呼び出すには

  • SEND METHOD ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。

プロパティへのアクセス

プロパティには、次のように ASSIGN(または COMPUTE)ステートメントを使用してアクセスできます。

ASSIGNoperand1.property-name = operand2
ASSIGNoperand2 = operand1.property-name

オブジェクトハンドル - operand1

operand1 はオブジェクトハンドルとして定義する必要があり、プロパティがアクセスされるオブジェクトを識別します。オブジェクトがすでに存在している必要があります。

operand2

operand2 として、プロパティのフォーマットに対してデータ転送互換を必要とするフォーマットのオペランドを指定します。詳細については、データ転送の互換性規則の説明を参照してください。

property-name

オブジェクトのプロパティの名前です。

プロパティ名が Natural 識別子構文に対応する場合は、次のように指定できます。

create object #o1 of class "Employee"
  #age := #o1.Age

プロパティ名が Natural 識別子構文に対応しない場合は、次のように山カッコで囲む必要があります。

create object #o1 of class "Employee"
  #salary := #o1.<<%Salary>>

プロパティ名は、インターフェイス名で修飾することもできます。同じ名前のプロパティが含まれる複数のインターフェイスがオブジェクトにある場合は、修飾が必要になります。この場合、修飾したプロパティ名は山カッコで囲む必要があります。

create object #o1 of class "Employee"
  #age := #o1.<<PersonalData.Age>>

例:

define data
  local
  1 #i         (i2)
  1 #o         handle of object
  1 #p         (5) handle of object
  1 #q         (5) handle of object
  1 #salary    (p7.2)
  1 #history   (p7.2/1:10)
  end-define
  * ...
  * Code omitted for brevity.
  * ...
  * Set/Read the Salary property of the object #o.
  #o.Salary := #salary
  #salary := #o.Salary
  * Set/Read the Salary property of
  * the second object of the array #p.
  #p.Salary(2) := #salary
  #salary := #p.Salary(2)
  *
  * Set/Read the SalaryHistory property of the object #o.
  #o.SalaryHistory := #history(1:10)
  #history(1:10) := #o.SalaryHistory
  * Set/Read the SalaryHistory property of
  * the second object of the array #p.
  #p.SalaryHistory(2) := #history(1:10)
  #history(1:10) := #p.SalaryHistory(2)
  *
  * Set the Salary property of each object in #p to the same value.
  #p.Salary(*) := #salary
  * Set the SalaryHistory property of each object in #p
  * to the same value.
  #p.SalaryHistory(*) := #history(1:10)
  *
  * Set the Salary property of each object in #p to the value
  * of the Salary property of the corresponding object in #q.
  #p.Salary(*) := #q.Salary(*)
  * Set the SalaryHistory property of each object in #p to the value
  * of the SalaryHistory property of the corresponding object in #q.
  #p.SalaryHistory(*) := #q.SalaryHistory(*)
  *
  end

配列が値として正しく含まれるオブジェクトハンドルとプロパティの配列を使用するためには、次の知識が重要です。

オブジェクトハンドルの配列のオカレンスのプロパティは、次のインデックス表記で指定します。

#p.Salary(2) := #salary

配列が値として含まれるプロパティは、常に全体としてアクセスされます。したがって、プロパティ名でのインデックス表記は不要です。

#o.SalaryHistory := #history(1:10)

結果的に、配列が値として含まれるオブジェクトハンドルの配列のオカレンスのプロパティは、次のように指定します。

#p.SalaryHistory(2) := #history(1:10)