method-id methodA static. 01 s string value "Hello". procedure division. display s end method.
method-id methodB (paramA AS binary-short paramB AS binary-short) RETURNING paramC AS binary-short. set paramC = paramA * paramB end method.
コアのサンプルも参照してください。このサンプルは、[スタート> すべてのプログラム > Micro Focus Visual COBOL > サンプル] の [COBOL for JVM] (Windows) または $COBDIR/demo (UNIX) にあります。
メソッドは、静的メソッドまたはインスタンス メソッドのいずれかになり、デフォルトでインスタンスになります。インスタンス メソッドは、クラスの指定インスタンスで機能し、静的メソッドは指定インスタンスでは機能しません。
静的メソッドは、そのクラスの静的メソッドおよび静的フィールドにアクセスできます。また、そのクラスまたはその他のクラスのインスタンス メソッドおよびインスタンス フィールドにもアクセスできます。そのためには、必要なクラスのオブジェクトを作成し、そのオブジェクトを介してメソッドまたはフィールドにアクセスします。
たとえば、次のクラスには、静的メソッドとインスタンス メソッド、静的フィールドとインスタンス フィールドが含まれます。
class-id MyCounter. 01 totalCount binary-long static. 01 myCount binary-long. method-id New. procedure division. set myCount to totalCount set totalCount to totalCount + 1 end method. method-id GetCount. procedure division returning returnItem as binary-long. set returnItem to myCount end method. method-id GetTotalCount static. procedure division returning returnItem as binary-long. set returnItem to totalCount end method. method-id SetCount static. procedure division using by value aCount as binary-long. set totalCount to aCount end method. end class.
次に、上記のコードを呼び出すプログラムを示します。
program-id StaticInstanceProgram. 01 myInstance1 type MyCounter. 01 myInstance2 type MyCounter. procedure division. invoke type MyCounter::SetCount(10) set myInstance1 to new type MyCounter set myInstance2 to new type MyCounter display myInstance1::GetCount() *> displays 10 display myInstance2::GetCount() *> displays 11 display type MyCounter::GetTotalCount() *> displays 12 end program.
次に、上記のコードを呼び出すプログラムを示します。
program-id StaticInstanceProgram.01 myInstance1 type MyCounter.01 myInstance2 type MyCounter. procedure division. invoke type MyCounter::SetCount(10) set myInstance1 to new type MyCounter set myInstance2 to new type MyCounter display myInstance1::GetCount() *> displays 10 display myInstance2::GetCount() *> displays 11 display type MyCounter::GetTotalCount() *> displays 12 end program.
静的メソッドとインスタンス メソッドを使用するには、次のようにします。
抽象メソッドに実装はありません。抽象メソッドを使用するには、そのメソッドを継承し、継承するサブクラスで、メソッドの実装を提供します。抽象クラスには、抽象以外のメソッドと抽象メソッドを含めることができます。抽象以外のメソッドでは、デフォルトの実装が提供され、この実装はサブクラスのメソッドでオーバーライドできます。次に例を示します。
class-id MyAbstractClass abstract. 01 myField value 0 binary-long property. method-id AbstractMethod abstract. *> no implementation end method. method-id NonAbstractMethod. *> not abstract procedure division. set myField to 1 *> Default behavior, which can be overridden end method. end class.
抽象クラスの非抽象メソッドでは、デフォルトの実装が提供され、この実装はサブクラスのメソッドでオーバーライドできます。
class-id MySubClass inherits type MyAbstractClass. method-id AbstractMethod override. procedure division. *> Subclass method implements abstract method display "myField is: " myField *> displays 0 end method. method-id NonAbstractMethod override. procedure division. *> Subclass method overrides method that is not abstract set myField to 6 display "myField is: " myField *> displays 6 end method. end class.
抽象クラスでメソッドを定義して使用するには、次のようにします。
オーバーライド メソッドは、同じ名前と署名の継承される仮想メソッドをオーバーライドするメソッドです。
たとえば、サブクラス Circle はスーパークラス Shape から継承します。どちらのクラスにも Draw メソッドが含まれます。Circle サブクラスの Draw メソッドは、Shape スーパークラスの Draw メソッドをオーバーライドします。
class-id Shape. method-id Draw. display "let's draw a super shape" end method. end class. class-id Circle inherits type Shape. method-id Draw override. display "let's draw a circle" end method. end class.
オーバーライド メソッドを定義するには、次のようにします。
継承されたクラスでは最終メソッドをオーバーライドできません。仮想メソッド (最終として定義されるメソッド) のみをオーバーライドできます。
REDEFINE キーワードは、クラスから継承されるメソッドを非表示にする場合に使用されます。継承されるメソッドを非表示にするには、同じ名前を使用する派生クラスでそのメソッドを宣言して REDEFINE を指定します。
再定義メソッドは、スーパークラスのメソッドと同じ名前および署名のメソッドである点がオーバーライド メソッドと似ています。ただし、オーバーライド メソッドとは異なり、再定義メソッドは、その呼び出し方法に応じて実行する場合としない場合があります。メソッドが次のクラスにあるものとして定義される項目で呼び出されるとします。
たとえば、2 つのサブクラス Circle と Square があり、これらは Shapes スーパークラスから継承します。すべてのクラスに Draw メソッドがあります。Circle クラスの Draw メソッドは、Shapes スーパークラスの Draw メソッドをオーバーライドします。Square クラスの Draw メソッドは、Shapes スーパークラスの Draw メソッドを再定義します。
class-id Shape. method-id Draw. display "let's draw a super shape" end method. end class. class-id Circle inherits type Shape. method-id Draw override. display "let's draw a circle" end method. end class.
class-id Square inherits type Shape. method-id Draw redefine. display "let's draw a square" end method. end class.
Circle クラスと Square クラスは次のように呼び出すことができます。
program-id. RedefineSampleProgram. 01 myShape type Shape. 01 myCircle type Circle. 01 mySquare type Square. procedure division. set myShape to new type Shape set myCircle to new type Circle set mySquare to new type Square invoke myCircle::Draw *> Circle Draw method is invoked invoke mySquare::Draw *> Square Draw method is invoked *> Shape Draw method is hidden, redefined set myShape to myCircle *> Superclass instance is set to subclass invoke myShape::Draw *> Circle Draw method is invoked *> as it overrides Shape Draw method set myShape to mySquare *> Superclass instance is set to subclass invoke myShape::Draw *> Shape Draw method is invoked as *> Square Draw method doesn't override it end program.
上記の呼び出しにより、次の出力が生成されます。
let’s draw a circle let’s draw a square let’s draw a circle let’s draw a super shape
REDEFINE を使用する場所がもう 1 つあります。その場所は、スーパークラスのメソッドが FINAL として定義される場所であるため、オーバーライドはできません。この場合、REDEFINE を使用してスーパークラスのメソッドを非表示にすることができます。
FINAL として宣言されるメソッドは、サブクラスでオーバーライドされません。このため、クラスはスーパークラスを継承できますが、特定のスーパークラスのメソッドは、サブクラスでオーバーライドされません。
たとえば、MySuperClass から継承するクラス MySubClass があるとします。MySuperClass には、1 つの最終メソッドと 1 つの仮想 (最終ではない) メソッドがあります。サブクラスは仮想メソッドをオーバーライドしますが、最終メソッドの継承やオーバーライドはできません。
class-id MySuperClass. method-id VirtualMethod. *> Methods are virtual by default procedure division. display "Virtual method in the superclass" end method. method-id FinalMethod final. *> Final methods are not virtual procedure division. display "Final method in the superclass" end method. end class.
サブクラスは次のように定義されます。
class-id MySubClass inherits type MySuperClass. method-id VirtualMethod override. procedure division. display "Overridden virtual method in the subclass" end method. * method-id FinalMethod override. *>COBCH0954 Method 'FinalMethod' cannot OVERRIDE a nonvirtual method end class.
クラスは、次のように呼び出されます。
program-id FinalOverrideSampleProgram. 01 mySuper type MySuperClass. 01 mySub type MySubClass. procedure division. set mySuper to new type MySuperClass invoke mySuper::FinalMethod() invoke mySuper::VirtualMethod() set mySub to new type MySubClass invoke mySub::VirtualMethod() end program.
上記のサンプル プログラムにより、出力が次のように生成されます。
Final method in the superclass Virtual method in the superclass Overridden virtual method in the subclass
最終メソッドはサブクラスでオーバーライドできませんが、サブクラスで再定義できます。
EXTENSION キーワードは、メソッドを拡張メソッドとして宣言します。
拡張メソッドを使用すると、コードの編集や再コンパイルを行わずにメソッドを既存の型に追加できます。拡張メソッドは、オブジェクト インスタンスで利用可能な追加メソッドとして表示されますが、どの場所にも実装されます。
たとえば、次の拡張メソッドは、文字列の単語数を数えるメソッドを追加することで、文字列クラスを拡張します。class-id MyCount static. method-id CountWords extension. *> extension method is implicitly static procedure division using by value str as string returning wordCount as binary-long. set wordCount to str::Split(' ')::Length end method. end class.
拡張メソッドを宣言するには、次のようにします。
マネージ COBOL から拡張メソッドを呼び出すための特別な構文はありません。拡張メソッドは、他のメソッドと同様に使用されます。ただし、最初のパラメーターを、メソッドが呼び出されるインスタンスであるかのように指定する点を除きます。
parameter-1::method-name(more parameters)
JVM COBOL では、コンパイルの前にあらかじめロードされる拡張が 2 つあります。
JVM COBOL または .NET COBOL のどちらにコンパイルされるかに関わらず、この 2 つの拡張によって、マネージ COBOL で同じ結果が生成されることを確認します。詳細については、「拡張メソッドと演算子」を参照してください。
SYNC 変更子は、メソッドに送られる引数の値をロックするため、メソッドの処理中に引数の値が変わることはありません。
引数がメソッドに送られ、参照パラメーターとして受け取られると、パラメーターの値とその対応する送信引数が更新されます。SYNC 変更子を使用しない場合、メソッドの処理中に送信引数の値が不明になります。
メソッドに対する SYNC 変更子は、SYNC 文のメソッド全体のラッピングに相当します。
次に例を示します。
01 a binary-long value 20. ... invoke Adjust(a) display a *> displays 93 method-id Adjust sync. procedure division using reference x as binary-long. set x to x + 73 end method. end class.
上記の例では、SYNC 変更子はメソッド Adjust() に適用されます。これにより、メソッド内の変数 (この場合、ローカルでは変数 x、呼び出しコード内では変数 a) には、メソッドの処理が終わるまでアクセスできません。
FOR 句を指定すると、このメソッドは明示的なインターフェイス メンバーの実装になります。このメソッドを明示的に呼び出すことはできません。このメソッドは、インターフェイス型にキャストされているこのクラスのインスタンスで対応するメソッドが呼び出されたときに暗黙的に呼び出されます。
(FOR 句による) 明示的なインターフェイスの実装の使用は、クラスが 2 つの異なるインターフェイスを実装しており、これら 2 つのインターフェイスに同じ名前と署名を持つメソッドがある場合に特に役立ちます。この場合、FOR 句を使用すると、2 つの異なるインターフェイス用にメソッドの 2 つの異なる実装を提供できます。interface-id. "IAlarm1". method-id checkAlarm. procedure division using atime as binary-long. end method. end interface. interface-id. "IAlarm2". method-id checkAlarm. procedure division using atime as binary-long. end method. end interface. class-id BasicAlarm implements type IAlarm1 type IAlarm2. method-id checkAlarm for type IAlarm1. procedure division using atime as binary-long. ... end method. method-id checkAlarm for type IAlarm2. procedure division using atime as binary-long. ... end method. end class.