メソッド
このページの目的
このページで説明する部位を以下に示します。テンプレートを五つに分割したうちの五つ目の部位になります。
_method() メソッドは Rice クラスのインターフェースであるメソッドの振舞を定義します。メソッドはインスタンスに作用する、パラメータを取るインターフェースです。
このメソッドは Rtype クラスの定義で抽象メソッドとして宣言されています。したがって、Rtype 派生クラスで実装しなければいけません。
fake クラスに以下のメソッドを定義することによって、メソッドの定義方法を説明します。
Concatenate(string) : 内部データと引数を連結します。
Concatenate(fake) : 内部データと引数を連結します。
Release() : インスタンスを初期化状態に戻します。
目次:
メソッドとは
メソッドはインスタンスに作用する、ゼロ個以上のパラメータを取るインターフェースです。作用した結果として値を返します。その振舞は以下のようになるでしょう。
fake fakeInstance = new fake("初期データ");
string concatData = fakeInstance.Concatenate("+追加データ"); // 返り値は "初期データ+追加データ"。
string newInternalData = fakeInstance.Value; // 内部データも "初期データ+追加データ"。
このようなインスタンスに作用を及ぼす、パラメータを取るインタフェースがメソッドです。
第一引数 : string signature
メソッドが現れた場合、Rice はメソッドの名前とパラメータのクラス名からメソッドを呼び出す名前、メソッドシグネチャを作成します。
作成されたメソッドシグネチャは _method() メソッドの第一引数として渡されます。
第二引数 : VirtualMachine vm
第二引数として VirtualMachine クラスのインスタンスが渡されます。これはスクリプトを実行している仮想機械です。
例外を投げる必要があるときは、この引数から取得してください。例外が発生したソースファイル名や行数などの情報がセットされた例外が取得できます。
throw vm.GetRtypeException("例外のメッセージ", "例外名"); // 補足的な情報がセットされた例外。 |
第三引数 : Queue<Rtype> argqueue
Rice はメソッド呼び出しを解析してパラメータ(引数)を第三引数に格納して _method() メソッドに渡します。
第三引数には引数に対応する Rtype 派生クラスのインスタンスが出現順に入っています。
テンプレートの修正
_method() メソッドを fake クラスのために修正します。
1: | public override Rtype _method(string signature, VirtualMachine vm, Queue<Rtype> argqueue) { |
2: | switch (signature) { |
3: | case "Concatenate(" + Rstring.TYPENAME + ")": { // "Concatenate(string)" |
4: | InternalData += (Rstring)argqueue.Dequeue(); // 内部データを更新。 |
5: | return new Rfake(InternalData); // 内部データを返す。 |
6: | } |
7: | case "Concatenate(" + Rfake.TYPENAME + ")": { // "Concatenate(fake)" |
8: | fake f = (Rfake)argqueue.Dequeue(); |
9: | InternalData += f.InternalData; // 内部データを更新。 |
10: | return new Rfake(InternalData); // 内部データを返す。 |
11: | } |
12: | case "Release()": { // "Release()" |
13: | InternalData = null; // 初期化未済に戻す。 |
14: | return new Rvoid(); // 返り値無し。 |
15: | } |
16: | default: |
17: | return null; |
18: | } |
19: | } |
switch 文を使い適切なルーチンへ分岐させています。各 case の値はクラスの TYPENAME を合成することで作成しています。
三~六行目で Concatenate(string) メソッドを定義しています。
四行目でメソッドに渡された引数を第三引数から取り出しています。メソッドシグネチャと第三引数に格納されているインスタンスはクラスと数が絶対に一致します。したがって、取り出した引数は安全にキャストすることが出来ます。
フィッタの説明で述べたように、Rstring クラスは C# の string へ暗黙的にキャストできるので InternalData と 引数を連結代入できます。
五行目で連結した結果を Rfake クラスの新しいインスタンスとして返しています。
七~十一目で Concatenate(fake) メソッドを定義しています。
八行目でメソッドに渡された引数を第三引数から取り出しています。メソッドシグネチャと第三引数に格納されているインスタンスはクラスと数が絶対に一致します。したがって、取り出した引数は安全にキャストすることが出来ます。
Rfake クラスの定義の中なので、Rfake の private メンバにアクセスできます。そこで、InternalData と f (Rfake) の InternalData を連結代入しています。
十行目で連結した結果を Rfake クラスの新しいインスタンスとして返しています。
十二~十四行目で Release() メソッドを定義しています。
十三行目で内部データに null を代入してインスタンスを初期化未済の状態にしています。
Release() メソッドは値を返す必要がないので、Rvoid クラスのインスタンスを返しています。
メソッドルーチンから Rtype 派生クラスが返された場合は、第一引数に対応するメソッドが存在して処理が成功したことを示します。
メソッドに返り値が無い場合は Rvoid クラスのインスタンスを返してください。
default: で null を返しています。null は対応するメソッドが存在しなかったことによる処理失敗を表します。null が返された場合は Rice が例外を投げます。
オーバーロード
上記のコードは名前が同じメソッドを定義しています。
メソッド名は同じですが、メソッドシグネチャは "Concatenate(string)" と "Concatenate(fake)" で異なります。つまり、メソッド名が同じでも適切なルーチンを呼び出すことができます。
Rice では、パラメータの順番、数が異なる同じ名前のメソッドを定義できます。これをメソッドのオーバーロードといいます。
メソッドが無い場合の実装
クラスにメソッドが必要無い場合は、以下のように _method() メソッドを実装してください。
1: | public override Rtype _method(string signature, VirtualMachine vm, Queue<Rtype> argqueue) { |
2: | return null; |
3: | } |