すべての値型は、ボックス化と呼ばれるプロセスで参照型に変わることがあります。たとえば、オブジェクト参照を、binary-long などの値型に設定できます。ボックス化の際に、値がオブジェクト ヒープにコピーされ、参照がオブジェクト ヒープに戻されます。
ボックス化は、必要に応じて自動で行われます。たとえば、オブジェクトをパラメーターとして予測するメソッドに値型をパラメーターとして渡す場合などです。
明示的にボックス化するには、値型を汎用型 (.NET COBOL の System.Object や JVM COBOL の java.lang.Object など) に割り当てます。値型のボックス化を解除して、元の値型を復元できます。
データ項目の定義で TYPE classname を指定すると、次のようになります。
値型のサンプルを参照してください。このサンプルは [Start > All Programs > Micro Focus Enterprise Developer > Samples > Visual COBOL Samples] の [COBOL for .NET] にあります。
すべてのクラスにはルート オブジェクトが関連付けられています。このルート オブジェクトを使用して、そのフィールドやメソッドなどのクラスに関する情報を取得できます。型情報を取得するには、次の方法を使用します。
imperative-clause TYPE OF type-name
*>Value Types *>condition-value *>binary-char (unsigned) *>character *>binary-short, binary-long, binary-double (unsigned) *>float-short, float-long *>decimal *>DateTime (a framework type) *>Reference types *>object *>string *>Initializing declare correct as condition-value = true *> Can also infer variable type if the value has a well-defined type declare incorrect = false *> automatically a condition-value declare b as byte = h"2a" *> hex declare o as byte = o"52" *> octal declare b2 as byte = b"101010" *> binary declare person as object = null declare nam as string = "Dwight" declare grade as character = "B" declare now as type DateTime = type DateTime::Now *> No support for date/time literals declare amount as decimal = 35.99 declare gpa as float-short = 2.9 declare pi as float-long = 3.14159265 declare lTotal as binary-double = 123456 declare sTotal as binary-short = 123 declare usTotal as binary-short unsigned = 123 declare uiTotal as binary-long = 123 declare ulTotal as binary-long unsigned = 123 *>Type Information declare x as binary-long display x::GetType *> Prints System.Int32 display type of binary-long *> Prints System.Int32 display x::GetType::Name *> Prints Int32 *>Type Conversion declare f as float-short = 3.5 *> automatic conversion declare i = f as binary-long *> set to 3 (truncates decimal) end program. program-id Legacy. *> COBOL types not supported directly by other languages. *> Visual COBOL supports these types on all platforms. *> Only a few examples here 01 displayNumber pic 9(9).99. 01 computeNumber pic 9(9)V99. 01 alphaNumberic pic a(23). 01 binaryStorage pic x(12). *> Also groups and redefines - a few examples 01 arecord. 03 aSubRecord pic x(10). 03 aUnion pic 9(10) redefines aSubrecord. end program.
型変換では、ある型の式を別の型に変換できます。型変換には明示変換と暗黙変換の 2 種類があります。明示変換を実行するには、AS 指定または AS IF 指定を使用して変換後の型を指定する必要があります。この種類の変換の例を次に示します。
Declare myAnimal as type Animal Declare myWarthog as type Warthog … Set myWarthog to myAnimal as type Warthog *> Convert type Animal to type Warthog
この例では、Animal 型のすべてのオブジェクトが Warthog 型であるわけではないため明示変換が必要です。
Set myAnimal to myWarthog
Warthog 型は Animal 型から派生するため、変換は常に正当なものであり、暗黙的に行うことができます。同様に、暗黙変換を使用して、Animal 型のパラメーターを値によって渡すすべてのメソッドに引数として myWarthog を渡すことができます。
型 S から型 T への暗黙変換は、次の場合に許可されます。
01 appDomain type System.AppDomain. 01 obj object. 01 myList type List[string]. 01 myEnumerable type IEnumerable[string]. 01 objArray object occurs 10. 01 strArray string occurs 10. set obj to appDomain *> type System.AppDomain derives from System.Object set appDomain to obj *> produces compile time error set myEnumerable to myList *> List[string] implements IEnumerable[string] set objArray to strArray *> source element type derives from target element type
.NET COBOL では、どの値型も System.Object 型または System.ValueType 型のいずれかの参照型に変換できます。また、列挙型は System.Enum 型に変換できます。
JVM COBOL では、プリミティブ型をボックス化された型に次のように変換できます。シグネチャ S を持つ匿名メソッドは、同じシグネチャおよび戻り値の型を持つ任意のデリゲート型に変換できます。また、パラメーターのない匿名メソッドは、同じ戻り値の型を持つ任意のデリゲート型に変換できます。
メソッド名が method-name であるメソッド グループで、シグネチャが S で戻り値の型が R のデリゲート型に変換できるのは、そのメソッド グループ内に同じシグネチャおよび戻り値の型を持つメソッド (つまり、指定された名前のメソッド) がある場合です。
型 S から型 T への明示変換 (キャストとも呼ばれる) は、次の場合に許可されます。
キャストに失敗すると、例外がスローされます (.NET の場合は InvalidCastException、JVM の場合は ClassCastException)。これを避けるには、INSTANCE OF を使用して有効なキャストかどうかを最初にテストするか、例外ブロックでキャストをラップします (詳細については、「TRY 文」を参照)。または、AS IF 指定を使用して、無効なキャストの場合はターゲット オブジェクトを null に設定して例外をスローしないように設定します (詳細については、「cast-expression」を参照)。
明示参照変換の例を次に示します。01 appDomain type System.AppDomain. 01 obj object. 01 myList type List[string]. 01 myEnumerable type IEnumerable[string]. 01 objArray object occurs 10. 01 strArray string occurs 10. *> Following allowed as type System.AppDomain derives from object set appDomain to obj as type System.AppDomain *> Following allowed as list[string] implements IEnumerable[string] set myList to myEnumerable as type List[string] *> Following allowed as there exists an explicit reference conversion *> from object (the element type of objArray) to string (element type of strArray) set strArray to objArray as string occurs any *> explicit conversions can be used anywhere… display obj as type System.AppDomain set obj to type of object *> sets obj to a System.Type object *> The following will throw an exception set appDomain to obj as type System.AppDomain *> *> this statement does not fail, but sets myString to null *> set myString to myObject as if stringobj-object は System.AppDomain インスタンスを参照すると明示した場合に、実際には System.Type インスタンスを参照していると、例外が次のようにスローされます。
*> these statements fail if uncommented *> set obj-object to obj-type *> set obj-app-domain to obj-object as type System.AppDomain
.NET COBOL では、System.Object 型または System.ValueType 型の項目を明示的に値型に変換できます。System.Enum 型の項目は列挙型に変換できます。
01 obj object. 01 dt type System.DateTime. Set obj to dt *> this is an implicit conversion using boxing Set dt to obj as type System.DateTime *> explicit unboxing conversionJVM COBOL では、次の型をプリミティブ型に変換できます。
変換演算子は、あるデータ型 (整数に定義した型など) のデータ項目を別のデータ型に変換します。変換演算子はオーバーロードできるため、適切な変換演算子が呼び出しコードのパラメーター型に従って使用されます。
暗黙変換の作成
たとえば、時間および分を含む型 Timer は、次の変換演算子を使用して binary-long として分に変換されます。
operator-id Implicit (a as type Timer) returning b as binary-long. set b to a::Hour * 60 + a::Minutes end operator.
この演算子は、次のような文で使用できます。
set myMins to timer3
同様に、次の変換演算子を使用して、binary-long データ項目 (分を表す) から、時間および分で表される型 Timer に変換できます。
operator-id Implicit (a as binary-long) returning b as type Timer. set b to new Timer declare hour as binary-long = a / 60 set b::Hour to hour set b::Minutes to a - 60 * hour end operator.
この演算子は、次のような文で使用できます。
set timer4 to myMins
暗黙変換は、割り当てやメンバーの呼び出しなどのあらゆる場所で行われます。
暗黙変換は暗黙的または明示的に呼び出すことができます。たとえば、次の文はどちらも暗黙変換を呼び出します。
set myMins to timer3 set myMins to timer3 as binary-long
変換が信頼できる場合 (情報が失われず、例外がスローされない場合)、暗黙変換を使用します。
operator-id Explicit (a as String) returning b as type Timer. 01 strH String. 01 strM String. 01 colonPos binary-long value 0. 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::Hour to type Int32::Parse(strH) set b::Minutes to type Int32::Parse(strM) catch display "Invalid time format" end-try end operator.
明示変換は、変換後の型を明示的に提示する文でのみ行われます。たとえば、変換演算子が明示として定義される場合、次の 2 番目の文のみが機能します。
set timer4 to myString *> fails to compile as no implicit conversion exists set timer4 to myString as type Timer *> succeeds
変換で情報が失われたり、例外がスローされる可能性がある場合、(暗黙変換ではなく) 明示変換を使用します。上記の例では、文字列にテキストが含まれるか、何らかの理由で文字列が無効になります。この場合、失敗を処理するには try-catch ブロックが必要です。