Home Notices Documents Classes Download Others Rice
Documents  >  開発  >  動的組み込みクラスの実装  >  メソッド
メソッドの実装

このページの目的

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



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

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

_method()メソッドはクラスのインターフェースであるメソッドの振舞を定義するためのメソッドです。メソッドはインスタンスに作用する、パラメータを取るインターフェースであり、C#のメソッドに相当します。


最初のセクションでメソッドについて説明します。

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

最後に実装の例を示すためのセクションを設けます。

メソッドとは

メソッドはインスタンスに作用する、ゼロ個以上のパラメータを取るインターフェースです。

メソッドの振舞をfileクラスを例として示します。


file someFile = new file("c:\somewhere....");

file newFile = someFile.CopyTo("c:\anotherlocation...");


CopyTo()がメソッドです。例に示すようにsomeFileのCopyTo()にパラメータとしてパスを渡して呼び出すことでsomeFileがそのパスにコピーされます。そして、コピーされたファイルを表すfileクラスのインスタンスがメソッド呼出の結果として返ります。このようなインスタンスに作用を及ぼす、パラメータを取るインタフェースがメソッドです。

インスタンスに作用した結果、呼出インスタンスの状態が変わることもありますし変わらないこともあります。メソッドから値が返ることもありますし返らないこともあります。


メソッドが呼び出された時のRiceの振舞を説明します。

メソッドが呼び出された時、Riceはメソッドの名前と引数(パラメータ)のクラス名からメソッドを呼び出す名前(メソッドシグネチャ)を作成します。上の例で言えば、メソッドの名前がCopyToで引数のクラス名がstringなので、メソッドシグネチャ CopyTo(string) を作成します。このメソッドシグネチャと引数を渡してsomeFileの_method()メソッドを呼び出すことでCopyToに対応する処理が実行されるわけです。

第一引数 : string signature

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

メソッドシグネチャの生成規則について引数の数を増やしながら順に説明します。ここでは仮に、インスタンスを"someIns"メソッドを"SomeMethod"とします。


引数のない場合。

someIns.SomeMethod()

メソッド名の後に空の括弧が指定された場合です。この場合はメソッドシグネチャはSomeMethod()となります。


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

someIns.SomeMethod("引数の文字列")

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


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

someIns.SomeMethod("引数の文字列", 10)

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


引数が三つ以上。

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


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

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

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


SomeMethod(list)

SomeMethod(list{string})

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

第二引数 : VirtualMachine vm

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

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

例えば


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


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

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

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

第三引数 : Queue<Rtype> argqueue

メソッド呼出で渡された引数がargqueueに格納されて_method()メソッドに渡されます。

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


引数のない場合。

someIns.SomeMethod()

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


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

someIns.SomeMethod("引数の文字列")

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


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

someIns.SomeMethod("引数の文字列", 10)

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

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


引数が三つ以上。

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

実装の一案

signatureにメソッドシグネチャが、argqueueに実際の引数が出現順に格納されていることを利用して必要な処理を行えます。

ここではtemplateクラスのために引数のないメソッド - MethodA() - とstringクラスの引数を一つとるメソッド - MethodB("引数") - の実装例を示してみます。

1:public override Rtype _method(string signature, VirtualMachine vm, Queue<Rtype> argqueue) {
2:switch (signature) {
3:case "MethodA()": {
4:// 必要な処理があるときはここに実装する。
5:// Rvoidクラスのインスタンスを返している。Rvoidクラスは返り値が無いことを示している。
6:return new Rvoid();
7:}
8:case "MethodB(" + Rstring.TYPENAME + ")": {
9:string arg1 = (Rstring)argqueue.Dequeue();
10:// 必要な処理があるときはここに実装する。
11:// Rstringクラスのインスタンスを返している。つまりこのメソッドの返り値はstringである。
12:return new Rstring();
13:}
14:default:
15:return null;
16:}
17:}

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

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

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

この例では何もしていませんが、実際の組み込みクラスの実装ではcaseで分岐した後に必要な処理を行います。処理が終了したらRtype派生クラスを返していることに注意してください。Rtype派生クラスはメソッドが存在し処理が無事に終了したことを示します。

メソッドに返り値が無い場合はRvoidクラスのインスタンスを返してください。

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

メソッドが無い場合の実装

クラスにメソッドが必要無い場合もあります。

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

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

次のページでは

これでメソッドの実装についての説明は終了です。

次のページではアプリケーションへのクラスの動的な登録について説明します。

Next
Previous
Copyright © CookerGX All rights reserved.