Home Notices Documents Classes Download Others Rice
Documents  >  開発  >  動的組み込みクラスの実装  >  フィッタ
フィッタの実装

このページの目的

このページは概要のページで述べたように、Rtemplate.csを五つに分けた二つ目の部分を詳説します。



今回説明する部分では、_fitter()メソッドを定義しています。これはRtypeの定義で宣言されている抽象メソッドで、Rtypeの派生クラスで必ず実装しなければいけません。

したがって、組み込みクラスの実装では_fitter()メソッドを必ず定義しなければいけません。

_fitter()メソッドはインスタンスの初期化に関する振舞を定義するためのメソッドです。具体的にはnew式で呼び出されるフィッタがこのメソッドによって定義されます。


最初のセクションでnew式を説明します。

_fitter()メソッドで重要なのはメソッドの引数です。引数毎にセクションを設けて解説します。

最後に実装例とデフォルトフィッタのためのセクションを設けます。

new式

new式はインスタンスを生成するための式です。ここでは、new式をtemplateクラスを例にとって説明します。


new template()


new式はキーワードnewで始まる式です。newの次にはクラス名が続きます。クラス名は有効なクラス名であれば、組み込み/ユーザ定義クラスのどちらでも構いません。new式は、このクラス名によって生成するインスタンスのクラスを決定します。上記の例ではnewの後にtemplateが続くのでtemlateクラスのインスタンスが生成されます。

クラス名とクラス名に続く”()” - 引数の指定 - によってインスタンスに実行する初期化ルーチンの名前 - フィッタシグネチャ - を作成します。このシグネチャの作成規則については次のセクションで説明します。

生成されたインスタンスに対してフィッタシグネチャに対応する初期化ルーチンを呼び出して初期化を実行します。フィッタシグネチャに対応する初期化ルーチンが存在しなければ初期化失敗で例外が発生します。

初期化が成功した場合はそのインスタンスをnew式の結果として返します。


第一引数 : string signature

作成されたフィッタシグネチャは_fitter()の第一引数であるsignatureとしてメソッドに渡されます。

フィッタシグネチャの生成規則について引数の数を増やしながら順に説明します。


引数のない場合。

new template()

new式でクラス名の後に空の括弧が指定された場合です。この場合はフィッタシグネチャはtemplate()となります。


引数が一つ。stringクラスの引数一つ取る場合。

new template("引数の文字列")

フィッタシグネチャは、template(string)となります。引数が一つの場合は括弧の間に引数のクラス名がそのまま入ります。


引数が二つ。stirngクラスとintクラスの引数をとる場合。

new template("引数の文字列", 10)

フィッタシグネチャは、template(string,int)となります。引数が二つの場合は括弧の間に引数のクラス名が出現順にカンマで区切られて入ります。


引数が三つ以上。

引数が二つの時と同じです。括弧の間に引数のクラス名が出現順にカンマで区切られて入ります。


コンテナクラス - list、dictionary、stack、queue - のクラス名については注意が必要です。これらのクラスは内部に保持するクラスを指定できます。

例えば、素のlistクラスのクラス名はlistですが、stringクラスだけを保持するようにした場合のクラス名はlist{string}になります。他のコンテナクラスについても同様です。

これが、そのままフィッタシグネチャに現れることに注意してください。


template(list)

template(list{string})

この様にして作成されたフィッタシグネチャが_fitter()の第一引数であるsignatureとしてメソッドに渡されます。

第二引数 : VirtualMachine vm

第二引数としてVirtualMachineクラスのインスタンスが渡されます。これはスクリプトが実行されている仮想機械を表します。

この引数のほぼ唯一の使用目的は例外クラスのインスタンスの取得です。もし例外を投げる必要があるときはVirtualMachineから取得してください。

例えば


throw vm.GetRtypeException("例外のメッセージ");


_fitter()メソッド内から投げる例外ですので、RtypeExceptionクラス(クラス関連の例外を想定している)を用いるのが適切です。そこでGetRtypeException()でそのインスタンスを取得して投げています。

この引数は、例外についての詳細なメッセージを持たせたい場合に役に立ちます。また、例外の発生場所に近いところから例外を投げれば補足的な情報もより正確になります。補足的な情報とは例外が発生したソースファイル名や行数などの位置情報です。VirtualMachineクラスから例外を取得すれば、それらの情報は自動的に例外にセットされます。

C#としての普通の例外を投げても、それはすぐ捕捉されてUnknownExceptionクラスに変換されます。その際に補足的な情報が自動的にセットされるので、それほど神経質になる必要はありません。

第三引数 : Queue<Rtype> argqueue

new式で渡された引数がargqueueに格納されて_fitter()メソッドに渡されます。

argqueueについて引数の数を増やしながら順に説明します。


引数のない場合。

new template()

この場合は空のQueue<Rtype>が渡されます。nullでは無いことに注意してください。


引数が一つ。例えばstringクラスの引数一つ取る場合。

new template("引数の文字列")

フィッタシグネチャがtemplate(string)となるので、argqueueはRstringクラスのインスタンスを一つ持ちます。この例の場合ならそのRstringインスタンスの値は"引数の文字列"となります。


引数が二つ。例えばstirngクラスとintクラスの引数をとる場合。

new template("引数の文字列", 10)

フィッタシグネチャがtemplate(string,int)となるので、argqueueはRstringクラスのインスタンス、次にRintクラスのインスタンスを持ちます。この例の場合ならそのRstringインスタンスの値は"引数の文字列"となり、Rintクラスのインスタンスの値は10です。

この様にargqueueには引数に対応するインスタンスが出現順に入っています。


引数が三つ以上。

引数が二つの時と同じです。argqueueに引数に対応するインスタンスが出現順に入ります。

実装の一案

signatureにフィッタシグネチャが、argqueueに実際の引数が出現順に格納されていることを利用して必要な初期化を行えます。

ここではtemplateクラスのために引数のないフィッタ - template() - とstringクラスの引数を一つとるフィッタ - template(string) - の実装例を示してみます。

1:public override bool _fitter(string signature, VirtualMachine vm, Queue<Rtype> argqueue) {
2:switch (signature) {
3:// new template()
4:case TYPENAME + "()": {
5:// 必要な処理があるときはここに実装する。
6:return true;
7:}
8:// new template(string)
9:case TYPENAME + "(" + Rstring.TYPENAME + ")": {
10:string arg1 = (Rstring)argqueue.Dequeue();
11:// 必要な処理があるときはここに実装する。
12:return true;
13:}
14:default:
15:return false;
16:}
17:}

この例ではswitch文を使いsignatureに格納されたフィッタシグネチャを判定して条件分岐させています。各caseの値はクラスのTYPENAMEを合成することで作成できます。二つ以上の引数のときは引数のクラス名の間に","を挟めば引数の数が幾つになっても正しく条件分岐できます。

argqueueには実際の引数が出現順に基底クラスであるRtypeクラスのインスタンスとして格納されています。つまり、フィッタシグネチャの引数の順番と完全に対応しているのですからcaseの値を合成した順番に従ってargqueueから取り出してRtype派生クラスにキャストすれば必要な引数が正しく取得できます。

上の例でRtype から Rstring にキャストした後に string に暗黙的に変換されています。組み込みクラスのキャストについてはマニュアルを参照するかVisual Studio のオブジェクトブラウザーで確認してくさだい。

この例では何もしていませんが、実際の組み込みクラスの実装ではcaseで分岐した後に必要な初期化を行います。初期化が終了したらtrueを返していることに注意してください。trueはフィッタが存在して初期化が成功したことを示します。

default:でfalseを返しています。falseは適切なフィッタが存在しなかったことによる処理失敗を表します。falseが返された場合は例外が投げられます。

デフォルトフィッタ

引数のないフィッタをデフォルトフィッタと呼びます。

上記の実装例ではデフォルトフィッタを明示的に実装していますが、明示的に実装されたデフォルトフィッタが無い場合はRiceがそれを暗黙的(自動的)に実装します。つまり、必要が無い場合はデフォルトフィッタは実装しなくても構いません。暗黙的に実装されたデフォルトフィッタは宣言文で返されるインスタンスと同じものを返します。

フィッタが無い場合の実装

クラスにフィッタが必要無い場合もあります。

そのような場合は以下のように_fitter()メソッドを実装してください。

1:public override bool _fitter(string signature, VirtualMachine vm, Queue<Rtype> argqueue) {
2:return false;
3:}

次のページでは

これでフィッタの実装についての説明は終了です。_fitter()メソッドが正しく実装されていればクラスのインスタンスも正しく生成されます。

次のページではクラスのインターフェースであるセッタの実装について説明します。

Next
Previous
Copyright © CookerGX All rights reserved.