このドキュメントでは、クラスを定義および使用してアプリケーションを開発する方法について説明します。
次のトピックについて説明します。
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 クラスモジュールを作成するには
CREATE OBJECT
ステートメントを使用して、クラスタイプの Natural オブジェクトを作成します。
DEFINE CLASS
ステートメントは、クラスの名前、クラスがサポートするインターフェイス、およびそのオブジェクトの構造を定義します。
クラスを指定するには
DEFINE CLASS
ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。
クラスの各インターフェイスは、クラス定義内部の INTERFACE
ステートメントで指定されます。 INTERFACE
ステートメントは、インターフェイスの名前と多数のプロパティおよびメソッドを指定します。 COM クラスとして登録されるクラスについては、インターフェイスのグローバルユニーク ID も指定されます。
クラスには 1 つ以上のインターフェイスを定義できます。 インターフェイスごとに 1 つの INTERFACE
ステートメントがクラス定義に指定されます。 各 INTERFACE
ステートメントには 1 つ以上の PROPERTY
節および METHOD
節が含まれます。 通常、1 つのインターフェイスに含まれるプロパティとメソッドは、技術またはビジネスのいずれかの観点から関連付けられます。
PROPERTY
節はプロパティの名前を定義し、オブジェクトデータエリアからプロパティに変数を割り当てます。 この変数を使用して、プロパティの値を保存します。
METHOD
節はメソッドの名前を定義し、メソッドにサブプログラムを割り当てます。 このサブプログラムを使用して、メソッドを実装します。
インターフェイスを定義するには
INTERFACE
ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。
PROPERTY
ステートメントは、複数のクラスが同じインターフェイスを異なる方法で実装するときにのみ使用されます。 この場合、クラスは同じインターフェイス定義を共有し、Natural コピーコードからインクルードします。 次に PROPERTY
ステートメントを使用して、インターフェイス定義の外でオブジェクトデータエリアからプロパティに変数を割り当てます。 INTERFACE
ステートメントの PROPERTY
節と同様に、PROPERTY
ステートメントはプロパティの名前を定義し、オブジェクトデータエリアからプロパティに変数を割り当てます。 この変数を使用して、プロパティの値を保存します。
オブジェクトデータ変数をプロパティに割り当てるには
PROPERTY
ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。
METHOD
ステートメントは、複数のクラスが同じインターフェイスを異なる方法で実装するときにのみ使用されます。 この場合、クラスは同じインターフェイス定義を共有し、Natural コピーコードからインクルードします。 METHOD
ステートメントは、インターフェイス定義の外でサブプログラムをメソッドに割り当てるために使用されます。 INTERFACE
ステートメントの METHOD
節と同様に、METHOD
ステートメントはメソッドの名前を定義し、サブプログラムをメソッドに割り当てます。 このサブプログラムを使用して、メソッドを実装します。
サブプログラムをメソッドに割り当てるには
METHOD
ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。
メソッドは次のような一般形式の Natural サブプログラムとして実装されます。
DEFINE DATA statement * * Implementation code of the method * END
DEFINE DATA
ステートメントの詳細については、『ステートメント』ドキュメントを参照してください。
DEFINE DATA
ステートメントのすべての節はオプションです。
データの整合性を確保するために、インラインデータ定義ではなくデータエリアを使うことをお勧めします。
PARAMETER
節を指定すると、メソッドにパラメータや戻り値を指定することができます。
パラメータデータエリアの BY VALUE
とマークされたパラメータは、メソッドの入力パラメータです。
BY VALUE
とマークされていないパラメータは、"BY REFERENCE" によって渡される入力/出力パラメータです。 これがデフォルトです。
BY VALUE RESULT
とマークされている最初のパラメータが、メソッドの戻り値として返されます。 複数のパラメータがこのようにマークされている場合は、その他のパラメータは入力/出力パラメータとして扱われます。
OPTIONAL
としてマークされているパラメータは、Natural バージョン 4.1 以降のすべてのリリースで使用可能です。 オプションのパラメータは、メソッドが呼び出される場合は指定する必要はありません。 SEND METHOD
ステートメントで nX
表記を使用することにより、これらを未指定にしておくことができます。
メソッドサブプログラムが、クラス定義内の対応する METHOD
ステートメントに指定されたものとまったく同じパラメータを受け入れるようにするには、インラインデータ定義ではなくパラメータデータエリアを使用します。 対応する METHOD
ステートメント内のものと同じパラメータデータエリアを使用します。
メソッドサブプログラムでオブジェクトデータ構造にアクセスするために、OBJECT
節を指定できます。 メソッドサブプログラムがオブジェクトデータに正しくアクセスできるようにするには、インラインデータ定義ではなくローカルデータエリアを使用します。 DEFINE CLASS
ステートメントの OBJECT
節に指定されているものと同じローカルデータエリアを使用してください。
GLOBAL
節、LOCAL
節、および INDEPENDENT
節は、他の任意の Natural プログラムで使用できます。
技術的には可能ですが、通常はメソッドサブプログラムで CONTEXT
節を使用することは意味がありません。
次の例は、特定の人物に関するデータをテーブルから検索します。 検索キーは BY VALUE
パラメータとして渡されます。 結果のデータは、"BY REFERENCE" パラメータで返されます。"BY REFERENCE" はデフォルト定義です。 メソッドの戻り値は BY VALUE RESULT
指定によって定義されます。
ローカルの 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
クラスのインスタンスを作成するには
CREATE OBJECT
ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。
オブジェクトの特定メソッドを呼び出すには
SEND METHOD
ステートメントを使用します。詳細については『ステートメント』ドキュメントを参照してください。
プロパティには、次のように ASSIGN
(または COMPUTE
)ステートメントを使用してアクセスできます。
ASSIGN operand1.property-name = operand2 |
ASSIGN operand2 = operand1.property-name |
operand1 はオブジェクトハンドルとして定義する必要があり、プロパティがアクセスされるオブジェクトを識別します。 オブジェクトがすでに存在している必要があります。
operand2 として、プロパティのフォーマットに対してデータ転送互換を必要とするフォーマットのオペランドを指定します。 詳細については、データ転送の互換性規則の説明を参照してください。
オブジェクトのプロパティの名前です。
プロパティ名が 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)