メソッド

メソッドは、その呼び出し時に実行されるコードのブロックを定義します。

method-specification

method-header constraints-paragraph procedure-division

method-header

access-modifier attribute-clause

method-id methodA static.
01 s string value "Hello".
procedure division.
   display s
end method.

コアのサンプルも参照してください。このサンプルは、[スタート > すべてのプログラム > Micro Focus Enterprise Developer > Samples] の COBOL for JVM の下にあります。

静的メソッドとインスタンス メソッド

メソッドは、静的メソッドまたはインスタンス メソッドのいずれかになり、デフォルトでインスタンスになります。インスタンス メソッドは、クラスの指定インスタンスで機能し、静的メソッドは指定インスタンスでは機能しません。

静的メソッドは、静的メソッドのみを呼び出し、静的フィールドのみにアクセスできます。静的メソッドは、静的クラスまたはインスタンス クラスに存在します。静的メソッドがインスタンス クラスにある場合、そのクラスからインスタンス化されるオブジェクトはすべて、静的メソッドの単一コピーを共有します。

例えば、次のクラスには、静的メソッドとインスタンス メソッド、静的フィールドとインスタンス フィールドが含まれます。

       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()         *> 10 を表示
           display myInstance2::GetCount()         *> 11 を表示
           display type MyCounter::GetTotalCount() *> 12 を表示

       end program.
       

静的メソッドとインスタンス メソッドを使用するには、次のようにします。

  • 静的メソッドを宣言するには、STATIC キーワードを使用します。メソッドが静的クラスにある場合、STATIC を指定してください。
  • インスタンス メソッドを宣言するには、キーワード STATIC は使用しないでください。
  • 静的メソッドにアクセスするには、クラスの名前の後に :: を続けてメソッド名を使用します。次に例を示します。 MyCounter::GetTotalCount() 上記のコードではこのようになります。
  • インスタンス メソッドにアクセスするには、インスタンス オブジェクトの名前の後に :: を続けてメソッドを使用します。次に例を示します。 myInstance1::GetCount() 上記のコードではこのようになります。

インスタンス メソッドの変更子

次の変更子は、メソッドが継承する範囲とメソッドが継承される範囲を示します。

ABSTRACT
空のメソッドを宣言します。抽象メソッドを使用するには、そのメソッドを継承し、必要なコードをサブクラスにインクルードする必要があります。
OVERRIDE

該当のメソッドが、同じ名前と署名の継承されたメソッドをオーバーライドすることを指定します。

REDEFINE

サブクラスに再定義メソッドが含まれるスーパークラスのメソッドを非表示にします。REDEFINE キーワードは、再定義メソッドを含むサブクラス内にあるものとして定義される項目で再定義メソッドが呼び出された場合のみスーパークラスのメソッドを非表示にします。

FINAL
派生クラスがメソッドをこれ以上オーバーライドしないようにします。

つまり、キーワードは次のように解釈できます。

  • 抽象メソッドでは、メソッドの名前と署名が提供されます。
  • 仮想メソッドは、メソッドの最初の実装です。
  • オーバーライド メソッドは、メソッドの別の実装です。
  • 最終メソッドは、メソッドの最後の実装です。

抽象メソッド

抽象メソッドに実装はありません。抽象メソッドを使用するには、そのメソッドを継承し、継承するサブクラスで、メソッドの実装を提供します。抽象クラスには、抽象以外のメソッドと抽象メソッドを含めることができます。抽象以外のメソッドでは、デフォルトの実装が提供され、この実装はサブクラスのメソッドでオーバーライドできます。次に例を示します。

class-id MyAbstractClass abstract.
       01 myField  value 0 binary-long property.

       method-id AbstractMethod abstract. *> 実装なし
       end method.

       method-id NonAbstractMethod.       *> 抽象以外
       procedure division.
            set myField to 1   *> デフォルトの動作、オーバーライド可能
       end method.

       end class.

抽象クラスには、抽象以外のメソッドを含めることができます。これらのメソッドでは、デフォルトの実装が提供され、この実装はサブクラスのメソッドでオーバーライドできます。

       class-id MySubClass inherits type MyAbstractClass.

       method-id AbstractMethod override.
       procedure division.
           *> サブクラスのメソッドは抽象メソッドを実装する
           display "myField is: " self::myField  *> 0 を表示
       end method.

       method-id NonAbstractMethod override.
       procedure division.
           *> サブクラスのメソッドは、抽象以外のメソッドをオーバーライドする
           set self::myField to 6
           display "myField is: " self::myField  *> 6 を表示
       end method.

       end class.

抽象クラスでメソッドを定義して使用するには、次のようにします。

  • ABSTRACT キーワードを使用して抽象のメンバーを定義し、抽象以外のメンバーの場合は省略します。抽象メンバーは、抽象クラス内になければなりません。
  • サブクラスは抽象スーパークラスを継承し、サブクラスには、スーパークラスのすべての抽象メンバーの実装を含める必要があります。ただし、サブクラス自体は抽象であり、この場合、実装は含まれません。
  • サブクラスのメソッドでは、キーワード OVERRIDE を使用する必要があります。
  • 抽象メソッドは private にはなりません。public、protected、または internal になります。

オーバーライド メソッド

オーバーライド メソッドは、同じ名前と署名の継承される仮想メソッドをオーバーライドするメソッドです。

例えば、サブクラス 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.

オーバーライド メソッドを定義するには、次のようにします。

  • method-id ヘッダで OVERRIDE 変更子を指定します。
  • メソッドの名前と署名が、継承されたクラスでオーバーライドされるメソッドと同じであることを確認します。

継承されたクラスでは最終メソッドをオーバーライドできません。仮想メソッド (最終として定義されるメソッド) のみをオーバーライドできます。

再定義メソッド

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 メソッドが呼び出される
           invoke mySquare::Draw   *> Square の Draw メソッドが呼び出される
                                   *> Shape の Draw メソッドが非表示になり、再定義される

           set myShape to myCircle *> スーパークラスのインスタンスがサブクラスに設定される
           invoke myShape::Draw    *> Circle の Draw メソッドが呼び出される
                                   *> Shape の Draw メソッドをオーバーライドする

           set myShape to mySquare *> スーパークラスのインスタンスがサブクラスに設定される
           invoke myShape::Draw    *> Shape の Draw メソッドが呼び出される
                                   *> Square の Draw メソッドは Shape の Draw メソッドをオーバーライドしない

       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. *> メソッドはデフォルトで仮想
       procedure division.
           display "Virtual method in the superclass"
       end method.

       method-id FinalMethod final. *> 最終メソッドは仮想ではない
       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 メソッド 'FinalMethod' は非仮想メソッドをオーバーライドできない

       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. *> 拡張メソッドは黙示的に静的
       procedure division using str as string
                          returning wordCount as binary-long.
            set wordCount to str::Split(' ')::Length
       end method.
       end class.

拡張メソッドを宣言するには、次のようにします。

  • メソッド ヘッダで EXTENSION キーワードを使用します。
  • メソッドは、ネストでも汎用でもない静的クラス内になければなりません。メソッドは暗黙的に静的になります。
  • メソッドの本文では、最初のパラメーターは拡張するタイプになります。これは、常に値パラメーターになります。

マネージ 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 self::Adjust(a)
       display a                 *> 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) には、メソッドの処理が終わるまでアクセスできません。

メソッドの呼び出し

メソッドを呼び出すには、INVOKE 文を使用するか、SET 文を使用してインラインで呼び出します。