20.2.7 オブジェクト指向による適合
オブジェクト参照データ項目にクラス名またはインタフェース名を指定すると,メソッドの呼び起こしやオブジェクト参照の転記の際に,適合がチェックされます。これによって,不当なメソッド呼び起こしや転記を防げます。適合するかどうかは,コンパイル時または実行時にチェックされます。
(1) オブジェクト参照の適合チェック
通常,オブジェクトを使用する場合は,オブジェクト参照を使用します。
オブジェクト参照の定義にクラス名やインタフェース名を指定した場合,そのオブジェクト参照を使用したプログラムが正しく動作するかが判定されます。
オブジェクト参照への値設定は,SET文の実行,メソッド呼び起こし時の引数への指定,または返却項目へのオブジェクト参照指定などによって発生します。オブジェクト参照へ値を設定する際,設定するデータの情報とオブジェクト参照に指定された情報との適合がチェックされ,適合するデータだけが設定できます。これによってオブジェクト参照が不適合なオブジェクトを指すことを防げます。
適合チェックの詳細については,マニュアル「COBOL2002 言語 標準仕様編」 「10.8.43 SET文」,および「COBOL2002 言語 標準仕様編」 「10.7 引数と返却項目の適合」を参照してください。
ここでは,適合チェックの概要について,説明します。
(a) クラス同士またはインタフェース同士の適合
クラス同士,またはインタフェース同士の適合は,クラスおよびインタフェースの継承関係によって,次の規則で判定されます。
-
あるクラスAに適合するクラスは,そのサブクラス(クラスAを継承するクラス),またはクラスAである。
-
あるインタフェースBに適合するインタフェースは,インタフェースBを継承するインタフェース,またはインタフェースBである。
例えば,クラス「CLASS-A」がクラス「CLASS-B」を継承している場合,「CLASS-Aは,CLASS-Bに適合している」といえますが,「CLASS-Bは,CLASS-Aに適合していない」ことになります。これは,CLASS-BがCLASS-Aを継承していないためです。
DATA DIVISION. WORKING-STORAGE SECTION. 01 OR1 USAGE OBJECT REFERENCE CLASS-A. 01 OR2 USAGE OBJECT REFERENCE CLASS-B. : PROCEDURE DIVISION. : SET OR2 TO OR1. *> 1. SET OR1 TO OR2. *> 2.
-
送り出し側作用対象であるOR1に指定されたCLASS-Aは,受け取り側作用対象であるOR2に指定されたCLASS-Bに適合しているので,このSET文は正しいと判定されます。
-
送り出し側作用対象であるOR2に指定されたCLASS-Bは,受け取り側作用対象であるOR1に指定されたCLASS-Aに適合していないので,このSET文はエラーとなります。
(b) インタフェースとクラスの適合
クラスとインタフェースの適合は,次の規則で判定されます。
-
あるインタフェースAに適合するのは,それを実装するクラスである。
クラスとインタフェースが適合するのは,上記のとおり「あるクラスがあるインタフェースに適合する」場合だけです。「あるインタフェースがあるクラスに適合する」ということはありません。
例えば,クラス「CLASS-A」がインタフェース「INTERFACE-B」を実装している場合,「CLASS-AはINTERFACE-Bに適合している」といえますが,「INTERFACE-BはCLASS-Aに適合していない」ことになります。
DATA DIVISION. WORKING-STORAGE SECTION. 01 OR1 USAGE OBJECT REFERENCE CLASS-A. 01 OR2 USAGE OBJECT REFERENCE INTERFACE-B. : PROCEDURE DIVISION. : SET OR2 TO OR1. *> 1. SET OR1 TO OR2. *> 2.
-
送り出し側作用対象であるOR1に指定されたCLASS-Aは,受け取り側作用対象であるOR2に指定されたINTERFACE-Bに適合しているので,このSET文は正しいと判定されます。
-
送り出し側作用対象であるOR2に指定されたINTERFACE-Bは,受け取り側作用対象であるOR1に指定されたCLASS-Aに適合していないので,このSET文はエラーとなります。
(c) メソッド呼び起こしの適合
INVOKE文によってメソッドを呼び起こす場合,そのメソッドが実行できるかどうかは,次の規則で判定されます。
-
INVOKE文で使用するオブジェクト参照にクラス名が指定されていれば,実行するメソッドは,そのクラスまたはそのクラスが継承するクラスのどちらかで定義されていなければならない。
-
INVOKE文で使用するオブジェクト参照にインタフェース名が指定されていれば,実行するメソッドは,そのインタフェースまたはそのインタフェースが継承するインタフェースのどちらかで定義されていなければならない。
クラス名またはインタフェース名指定のオブジェクト参照で,上記の規則に従っていないメソッドの呼び起こしがあると,コンパイル時にエラーとなります。
(2) 実装インタフェースの適合チェック
インタフェースを実装する場合,ファクトリ段落またはオブジェクト段落のIMPLEMENTS句にインタフェース名を指定します。このとき,インタフェースは,ファクトリオブジェクトまたはインスタンスオブジェクトが実装するインタフェースに適合しているかどうかがチェックされます。このチェックでは,次の条件が成立する場合だけ,適合しているとみなされます(適合条件の詳細については,マニュアル「COBOL2002 言語 標準仕様編」 「5.2.7 適合とインタフェース」を参照してください)。
-
インタフェースが定義する各メソッドに対して,同名のメソッドがオブジェクトにも存在する。
-
同名メソッドの引数と返却項目の定義が同じである。
このため,実装されるインタフェースの持つメソッド定義の集合は,それを実装するオブジェクトが持つメソッド定義と同じ集合か,またはその部分集合となります。
例として,次のようなメソッド定義集合のインスタンスオブジェクトとインタフェースがあるとします。
- クラス「CL-1」のインスタンスオブジェクトのメソッド定義集合
-
METH1,METH2,METH3
- インタフェース「INT-1」のメソッド定義集合
-
METH1,METH2
- インタフェース「INT-2」のメソッド定義集合
-
METH1,METH4
インタフェースINT-1のメソッドは,すべてクラスCL-1に含まれています。このため,インタフェースINT-1は,クラスCL-1に適合しているといえます。
一方,インタフェースINT-2は,クラスCL-1が持たないメソッドMETH4を含んでいます。このため,インタフェースINT-2は,クラスCL-1に適合していないといえます。
インタフェースINT-1,INT-2にIMPLEMENTS句を指定すると,コンパイル時に次のように判定されます。
- (インタフェースINT1の場合)
IDENTIFICATION DIVISION. CLASS-ID. CL-1. : OBJECT. IMPLEMENTS INT-1. …適合していると判定されます。 : END OBJECT. END CLASS CL-1.
- (インタフェースINT2の場合)
IDENTIFICATION DIVISION. CLASS-ID. CL-2. : OBJECT. IMPLEMENTS INT-2. …INT-2が持つMETH4がオブジェクト : にないため,適合エラーとなります。 END OBJECT. END CLASS CL-2.
(3) オブジェクトビューによる実行時の適合チェック
オブジェクトビューとは,一時的にASの指定どおりの記述を持つように,オブジェクト参照を扱うものです。オブジェクトビューの言語規則については,マニュアル「COBOL2002 言語 標準仕様編」 「4.3.2(4) オブジェクトビュー」を参照してください。
オブジェクトビューをオブジェクト参照に指定すると,コンパイル時にオブジェクト参照の適合がチェックされないで,プログラム実行時にオブジェクト参照が指すオブジェクトとオブジェクトビューの指定内容の適合がチェックされます。チェックは,オブジェクト参照にオブジェクトビューの情報(クラス名,インタフェース名など)が設定された場合の,オブジェクト参照の適合チェックと同等となります。
オブジェクトビューを指定して,プログラム実行時に適合をチェックする例を,次に示します。
-
クラス「CLASS-A」は,クラス「CLASS-B」を継承している。
-
CLASS-Aは,メソッド「METH-A」を,CLASS-Bは,メソッド「METH-B」を,それぞれ持っている。
DATA DIVISION. WORKING-STORAGE SECTION. 01 OR-B USAGE OBJECT REFERENCE CLASS-B. : PROCEDURE DIVISION. : INVOKE CLASS-A 'NEW' RETURNING OR-B. : INVOKE OR-B 'METH-A'. *> 1.
上記の場合,1.のINVOKE文は,OR-Bに指定されたCLASS-BがMETH-Aを持たないため,コンパイル時にエラーとなります。しかし,OR-Bが指すのはCLASS-Aから作成されたインスタンスオブジェクトなので,METH-Aを実装しています。このため,1.のINVOKE文では,METH-Aを実行できます。
このような場合,次のようにオブジェクトビューを指定すれば,コンパイルエラーとならないでプログラムを実行できます。
INVOKE OR-B AS CLASS-A 'METH-A'. オブジェクトビュー