タイプは、AS 構文または変換演算子を使用して他のタイプに変換できます。
マネージ COBOL では、次のタイプを区別します。
すべての値タイプは、ボックス化と呼ばれるプロセスで参照タイプに変わることがあります。例えば、オブジェクト参照を、binary-long などの値タイプに設定できます。
ボックス化は、必要に応じて自動で行われます。例えば、オブジェクトをパラメーターとして予測するメソッドに値タイプをパラメーターとして渡す場合などです。
明示的にボックス化するには、値タイプを汎用タイプ (.NET COBOL の System.Object や JVM COBOL の java.lang.Object など) に割り当てます。
値タイプのボックス化を解除して、元の値タイプを復元できます。
データ項目の定義でタイプ classname を指定する場合:
ボックス化の際に、値がオブジェクト ヒープにコピーされ、参照がオブジェクト ヒープに戻されます。参照がアクティブではなくなった場合 (オブジェクト ヒープに対して保持するものがプログラム内にないため)、オブジェクト ヒープのスペースは、ガベージ コレクターで最終的に再取得されます。
値タイプのサンプルを参照してください。このサンプルは [スタート > すべてのプログラム > Micro Focus Enterprise Developer > Visual COBOL Samples] にあります。
すべてのクラスにはルート オブジェクトが関連付けられています。このルート オブジェクトを使用して、そのフィールドやメソッドなどのクラスに関する情報を取得できます。タイプ情報を取得するには、次の方法を使用します。
imperative-clause TYPE OF object
例えば、.NET COBOL では次のようになります。
*> タイプ情報 01 x binary-long. display x::GetType *> System.Int32 を印刷する display type of binary-long *> System.Int32 を印刷する display x::GetType::Name *> Int32 を印刷する
例えば、JVM COBOL では次のようになります。
*> タイプ情報 01 x binary-long. display x::getClass *> System.Int32 を印刷する display type of binary-long *> System.Int32 を印刷する display x::getClass::Name *> Int32 を印刷する
変換演算子は、あるデータ タイプ (整数に定義したタイプなど) のデータ項目を別のデータ タイプに変換します。変換演算子はオーバーロードできるため、適切な変換演算子が呼び出しコードのパラメーター タイプに従って使用されます。
例えば、時間と分を含むタイプ Timer は、次の変換演算子を使用して binary-long として分に変換されます。
set myMins to timer3 ...
operator-id Implicit. procedure division using value a as type Timer returning b as binary-long. set b to a::pHour * 60 + a::pMins end operator.
同様に、次の変換演算子を使用して、binary-long データ項目 (分を表す) から、時間と分で表されるタイプ Timer に変換できます。
set timer4 to myMins ...
operator-id Implicit. procedure division using value a as binary-long returning b as type Timer. set b to new Timer if a >= 60 set b::pHour to 1 set b::pMins to a - 60 else set b::pMins to a end-if end operator.
暗黙変換の他に明示変換を定義できます。暗黙変換と明示変換は次のように異なります。
set timer4 to myString *> 失敗 set timer4 to myString as type Timer *> 成功
operator-id Explicit. 01 strH type String. 01 strM type String. 01 colonPos binary-long value 0. procedure division using value a as String returning b as Type Timer. set b to new Timer() set colonPos to a::IndexOf(":") try set strH to a::Substring(0 colonPos) set strM to a::Substring(colonPos + 1 2) set b::pHour to type Int32::Parse(strH) set b::pMins to type Int32::Parse(strM) catch display "Invalid time format" end-try end operator.
変換で情報が失われたり、例外がスローされる可能性がある場合、(暗黙変換ではなく) 明示変換を使用します。上記の例では、文字列にテキストが含まれるか、何らかの理由で文字列が無効になります。この場合、失敗を処理するには try-catch ブロックが必要です。
暗黙変換は暗黙的または明示的に呼び出すことができます。例えば、次の文はどちらも暗黙変換を呼び出します。
set myMins to timer3 set myMins to timer3 as binary-long
変換が信頼できる場合 (情報が失われず、例外がスローされない場合)、暗黙変換を使用します。
オブジェクト参照は、AS を使用して別のタイプのインスタンスにキャストできます。コンパイラは、操作がタイプ セーフかどうかをチェックできます。
次の例では、obj-object が System.AppDomain 参照を指し示すことがわかっているため、System.Object から System.AppDomain に向かってクラス階層を上方向にキャストできます。
*> obj-app-domain を obj-object に設定する *> 非コメント化する場合は失敗 set obj-app-domain to obj-object as type System.AppDomain *> 成功
キャストはインラインで可能なため、次の操作を実行できます。
display obj-object as type System.AppDomain::FriendlyName
キャストは、ターゲット タイプ (キャスト先のタイプ) がソース タイプから直接派生する場合 (あるいはその逆) のみ適しています。次の文では、クラスが階層に関連しないため、System.Type 参照 (obj-type) が System.AppDomain インスタンスを指し示すことはありません。
*>obj-app-domain を obj-type に タイプ System.AppDomain として設定する *> 非コメント化する場合は失敗
キャストが失敗すると、System.InvalidCastException が CLR からスローされます。この例外を避けるには、INSTANCE OF を使用して有効なキャストかどうかを最初にテストするか、例外ブロックでキャストをラップします (詳細は、例外処理の例を参照)。
実際に obj-object が System.Type インスタンスを参照している場合、obj-object が System.AppDomain インスタンスを参照すると断言すると、例外が次のようにスローされます。
*> 非コメント化する場合、これらの文は失敗 *> obj-object を obj-type に設定する *> obj-app-domain を obj-object にタイプ System.AppDomain として設定する