[前へ] [目次へ] [次へ]

メソッド


FGESではメソッドは実行可能なコードを含む唯一のオブジェクト型です。
メソッドは必ず所属クラスと対象クラスを持ち、 static ではないメソッドは呼び出しのホストとして
対象クラスか、その派生クラスのインスタンスを必要とします。

所属クラスはメソッドを定義するクラスで、 SelfType で示すことができ、 internal アクセス権限の評価に使用されます。
対象クラスはメソッドの呼び出しホストとなれるクラスを示し、 this の型として使用されます。
portable や super などを宣言しない限り、所属クラスと対象クラスは同一になります。

メソッドにはFGESメソッドとネイティブメソッドがあります。
FGESメソッドはFGES上で定義したメソッドで、ネイティブメソッドはC++レベルで定義されたメソッドです。
ネイティブメソッドはC++で記述された関数を呼び出すので、FGESだけでは記述できない動作を行うことができます。
また、一部のネイティブメソッドは呼び出し方法に制限があります。

C/C++と同じく、メソッド宣言のみを行い、定義を分割することができます。
構文1:宣言のみを行う(定義は同じ宣言を持つ定義構文を使用します)
   method メソッド宣言 ;

構文2:定義を行う(宣言がない場合は宣言を兼ねます)
   method メソッド宣言 {
      定義内容
   }


●メソッド宣言

   メソッドは呼び出しに使用する外部インターフェイスをメソッド宣言として定義する必要があります。
   これはC/C++の関数宣言と同種のもので、属性、戻り値型、引数の情報が含まれます。
   
   グローバルメソッド以外の定義中は SelfType で定義中のクラス(所属クラス)を示すことができます。
   サブタイプに対応するネイティブクラスでは SubType でサブタイプを示します。
   
   構文:
   属性1 戻り値型 メソッド名 ( 引数リスト ) 属性2

   ●属性1
      属性1にはアクセス属性、定義属性が含まれ、同一グループは同時に複数使用できません。
      異なるグループの属性は同時に使用することができます。
      アクセス制御グループが記述されていない場合はデフォルト属性になります。
      また、アクセス制御属性は参照に付与されるため、
      メソッドオブジェクト自体を取得すればアクセス制御属性に関わらず呼び出すことができます。
記述グループ意味
publicアクセス制御メソッドはどこからでも呼び出せます。
internalアクセス制御メソッドは同一クラスまたは派生クラス、注入クラスに所属するメソッドからのみ呼び出せます。
nativeアクセス制御メソッドはFGESレベルでは呼び出せません。
この属性はネイティブメソッドのために存在します。
staticホストメソッドはインスタンスを必要としません。
この属性を持つクラスメンバメソッドは特に「クラスメソッド」と呼びます。
この属性が設定されるとメソッド内でthisおよび自身のインスタンス変数が使用できなくなり、
クラス名::メソッド名() の形式で呼び出せるようになります。
また、暗黙にfinal属性も設定されます。
final継承制御メソッドを派生クラスでオーバーライドできなくなります。
required継承制御派生クラスまたは実装クラスでメソッドのオーバーライドまたは実装が強制されます。
この属性は抽象クラスまたはインターフェイスのメソッドにしか設定できません。
abstract継承制御メソッドは実装を持たず、派生クラスでメソッドの実装が強制されます。
この属性を持つクラスメンバメソッドは特に「抽象メソッド」と呼びます。
この属性は抽象クラスのメソッドにしか設定できません。
optional継承制御実装クラスでメソッドの実装が任意になります。
この属性はインターフェイスメソッドにしか設定できません。
overrideオーバーライド基底クラスにある同名のメソッドをオーバーライドします。
メソッド宣言の外部インターフェイスはオーバーライド対象メソッドと同じでなければいけません。
この属性が設定されるとメソッド内でオーバーライド対象メソッドオブジェクトを示すsuperが使用可能になります。
この属性はオーバーライド対象がabstract属性を持つ場合は使用できません。
forced_overrideオーバーライド基底クラスにある同名のメソッドを強制的にオーバーライドします。
メソッド宣言は基底クラスと異なっても構いませんが、
互換性のない形に変化させた場合は実行時に例外が発生する可能性があります。
この属性が設定されるとメソッド内でオーバーライド対象メソッドオブジェクトを示すsuperが使用可能になります。
この属性の使用は推奨されません。
implementsオーバーライド基底クラスにある同名の抽象メソッドを実装します。
メソッド宣言の外部インターフェイスは実装する対象メソッドと同じでなければいけません。
この属性は実装する対象がabstract属性を持たない場合は使用できません。
redefine再定義既に存在する同名のメソッドを再定義します。
メソッド宣言の外部インターフェイスは既存のメソッドと同じでなければいけません。
再定義前のメソッドオブジェクトは消滅するため、
既存の同メソッドへの参照は無効になり、メソッドが実行中であった場合例外が発生します。
この属性はネイティブメソッドには適用できません。
super対象制御メソッドは基底クラスを対象クラスとしてコンパイルされます。
この属性が設定されたメソッドは基底クラスで使用できる名前のみが使用でき、
同じ基底クラスを持つ他のクラスのインスタンスをホストとしてこのメソッドを呼び出せるようになります。
この属性は多重宣言でき、宣言した回数分基底クラスへさかのぼります。
この属性は通常継承している基底クラスのみを目標とすることができます。
portable対象制御メソッドはAnyClassを対象クラスとしてコンパイルされます。
この属性が設定されたメソッドはあらゆるクラスのインスタンスをホストとして呼び出せるようになります。
その代わり、thisからの静的名前解決は型検証付きの動的解決に変更され、
所属クラスと同等の定義をthisが持っていると仮定してコンパイルされます。
(同等の定義とは、属性および型が同じ状態を指し、通常injectを使用して生成します)
また、所属クラスのクラス共有変数への直接参照もSelfTypeを明示しなければいけません。
クラス共有変数の指定にthisを用いた場合、所属クラスではなくthisから見えている変数を示します。

   ●戻り値型
      戻り値型はメソッドを呼び出した後の評価型として使われます。
      FGESでの戻り値型は「なし」、「値返し」、「参照返し」の三種類です。
      構文1:なし
         void
      構文2:値返し(戻り値型名は 型名 解釈です)
         属性 戻り値型名
      構文3:参照返し(戻り値型名は 型名 解釈です)
         属性 戻り値型名 @

      また、属性として readonly または const を記述することで、戻り値の参照は読み取り専用となります。
      読み取り専用の参照からはメンバ参照時に全てのメンバが読み取り専用になり、
      const 属性を持たないクラスメンバメソッドが呼び出せなくなります。
      ( const 表記はC/C++との記述互換性のために認められており、同一に解釈されます)
      属性に何も記述しない場合は戻り値の参照は編集可能属性となります。
   
      戻り値型が「なし」のメソッドを呼び出す場合、
      呼び出しの後に評価する他の演算子や識別子があってはいけません。
      また、メソッドの実行を途中で終了して呼び出し元に戻る場合 return を使用します。
      
      戻り値型が「値返し」の場合、メソッドの実行は retval で終わる必要があります。
      また、 retval が実行され、呼び出し元が結果を要求している場合、戻り値型の一時オブジェクトが作成され、
      #Value または #operator= を用いて式の結果を代入してから呼び出し元に返されます。
      この時戻り値型のクラスに #Value が定義されていれば #Value が使用され、
      定義されていなければ #operator= が使用されます。
      一時オブジェクトを実体化するため、戻り値型が
      不完全型、抽象クラス、インターフェイス、実体化不可型であってはいけません。
      
      戻り値型が「参照返し」の場合、メソッドの実行は retref で終わる必要があります。
      また、 retref が実行されると式の結果オブジェクトの参照が呼び出し元に返されます。
      この時対象となったオブジェクトの寿命は変更されません。
      式の結果オブジェクトが一時オブジェクトやローカルオブジェクトであった場合、
      呼び出し元に戻った時点で既に消滅しており、無効参照が返されることになります。
      また、式の結果オブジェクトは戻り値型に暗黙に変換できる型
      (同じ型、派生型、戻り値型のインターフェイスをサポートしている型)でなければいけません。

   ●メソッド名
      メソッドの完全名を示し、VM全体で一意となるように宣言します。
      なお、クラス定義空間ではクラス名は自動的に補完され、
      インターフェイス定義空間ではインターフェイス名は自動的に補完され、
      既存クラスの対応インターフェイス追加中はクラス名およびインターフェイス名は自動的に補完されます。

      構文:
         クラス名 インターフェイス名 メソッド名

      クラス名は識別名の後に :: を付け、
      クラス内クラスを示す場合は :: でクラスパスを示します。
      クラス名が空欄の場合はグローバル定義空間を意味します。
      
      インターフェイス名は識別名の後に @@ を付け、
      クラス内インターフェイスを示す場合は @@ でクラスパスを示します。
      インターフェイス名を指定したクラスメンバメソッドは特にインターフェイスメソッドと呼びます。
      インターフェイス名が空欄の場合は通常のクラスメンバメソッドを意味します。
      
      例:
<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>
<  8>
<  9>
< 10>
< 11>
< 12>
   class A{
      
interface B{
         
method void C();
      }
   }
   
class D{
      
class E:implements A::B{
         
method void A@@B@@C();
      }
   }
   
   
method void D::E::A@@B@@C(){} 

   ●仮引数リスト
      メソッドの呼び出し時に必要な引数のリストです。
      引数は必ず参照渡しされ、デフォルト引数がある場合は該当する引数を省略できます。
      また、デフォルト引数があり、引数型に ? がない引数に空参照が渡された場合、デフォルト引数が使用されます。
   
      デフォルト引数式はコンパイル時に実行され、
      その結果オブジェクトをデフォルト引数オブジェクトとしてメソッドオブジェクトに保持します。
      なお、デフォルト引数式の結果オブジェクトが一時オブジェクトである場合、
      メソッドオブジェクトと同じ寿命に変更されます。
      また、式の結果オブジェクトは引数型に暗黙に変換できる型
      (同じ型、派生型、引数型のインターフェイスをサポートしている型)でなければいけません。
      さらに、デフォルト引数オブジェクトは使いまわされるので、
      編集可能な引数にデフォルト引数を付け、内容を変更すると次回以降の呼び出しでも変更は残ったままになります。

      仕様上引数リストの数に上限は設定されていませんが、
      現在のFGESコンパイラの制限として「式内で同時に扱えるオブジェクト数30」があるため、
      引数の数は多くとも20以内に収めることを推奨します。

      構文1:固定数の引数を取る場合、 , 区切りで必要なだけ引数情報を並べます
      引数情報1 , 引数情報2

      構文2:可変数の引数を取る場合、最後の引数情報として ... を記述します
      引数情報1 , 引数情報2 , ...

      ●引数情報
         引数情報は引数の型、属性、名前などを示し、変数宣言に似ています。
         変数宣言と異なり、デフォルトの属性が読み取り専用で、
         引数オブジェクトを変更する場合は明示的に属性として editable の指定が必要です。

         構文1:(引数型は 型名 解釈です)
         属性 引数型 引数名

         構文2:デフォルト引数を使う場合(引数型は 型名 解釈です)
         属性 引数型 引数名 = デフォルト引数式

         引数情報の属性として以下の記述が使用できます。
記述意味
editable引数オブジェクトを編集可能にします。
これを指定しない場合、引数は読み取り専用です。
depend引数オブジェクトのeditable/readable参照属性をthisと同じにします。
values値渡しを擬似的に行います。

         values 属性は引数型に values インターフェイスが定義されていなければ使用できません。
         コンパイラは実際の引数型を values インターフェイスのものに変更し、
         ローカル変数を作成し、 #Value を使用して渡された引数を値化するコードを生成します。
         例えば、次のメソッド( Integer クラスは values インターフェイスとして IInteger を定義しています)は

<  1>
<  2>
   method void A(values Integer n){
   } 

         以下のメソッドを記述したのと概ね同じことになります。
         (値のコピーに実際には #operator= ではなく #Value を用いる点が最大の違いです)
         なお、メソッドの外部インターフェイスの同一性判定はこの書き換え後に行われます。
<  1>
<  2>
<  3>
<  4>
   method void A(IInteger n_temp){
      
var Integer n;
      n=n_temp;
   } 

   ●属性2
      メソッドの呼び出し属性を以下から一つ指定します。
      呼び出しホストが関わるため、 static メソッドでは指定できません。
記述意味
(空欄)呼び出しのホストオブジェクトの内容を変更する可能性があります。
呼び出しのホストは編集可能(editable)参照でなければいけません。
const呼び出しのホストオブジェクトの内容を変更しません。
この属性が設定されるとthisが読み取り専用(readonly)参照になります。
depend戻り値型およびthiseditable/readable参照属性が呼び出し元のホストオブジェクトの参照属性になり、
const版とconst版のメソッドを多重定義しているように扱えます。
この属性が設定されると戻り値型およびthisは読み取り専用(readonly)参照としてコンパイルされますが、
実行時には呼び出し元の参照属性に設定されます。
この属性はコンテナクラスが保有する参照を返す時に便利です。

      depend 属性は以下の overload_class のような多重定義をしているように見えます。
<  1>
<  2>
<  3>
<  4>
<  5>
<  6>
<  7>
<  8>
<  9>
< 10>
< 11>
< 12>
   class depend_class{
      
var int n;
      
method int@ GetVar()depend{retref @n;}//実際にできる定義
   }
   
   
class overload_class{
      
var int n;
      
method int@ GetVar(){retref @n;}
      
method readonly int@ GetVar()const{retref @n;}
      
//C++では上記のような定義ができるが、
      //オーバーロードのないFGESではできないため、dependで対応している
   } 

●メソッド定義内容

   メソッドの実行内容を制御文、式を使用して記述します。
   定義内容の部分はメソッド定義空間となります。
   詳細については 制御文  演算子 などを参照してください。
   
   現在のFGESコンパイラのパス追跡は甘いので、
   戻り値を返すメソッドでは直属のブロックで retval または retref が必要になります。
   全ての分岐ブロックの中で retval または retref があっても検出できません。

[前へ] [目次へ] [次へ]

最終更新 2021/08/23