オブジェクトメソッドの定義と使用 - オブジェクトメソッドの概要
|
メソッド
|
|
•
|
メソッドは、Maple オブジェクトの宣言 時に定義されるプロシージャです。メソッドに関する注意点を以下に示します。
|
|
メソッド名は static と宣言されます。
|
|
•
|
Maple ではメソッド名は static として宣言されます。ほとんどの場合で、同一クラスのすべてのオブジェクトは、それらのメソッドについて同じプロシージャを使用します。そのため、メソッド名が static と宣言されていない場合は、各オブジェクトはプロシージャのコピーを別に持ちます。static オブジェクトに関する詳細は、「新規オブジェクトを作成する」を参照してください。
|
|
|
オブジェクトはメソッドに渡す必要があります
|
|
•
|
オブジェクトの内容にアクセスする必要があるメソッドを宣言する場合は、そのオブジェクトは、引数としてメソッドに渡される必要があります。これは、現在の呼び出しに関連するオブジェクトの内容に、オブジェクトの要素への直接アクセスまたは self 変数によってアクセス可能なオブジェクト指向言語と対照的です。メソッドは、メソッドが宣言された同じクラスのすべてのオブジェクトのローカル変数へアクセスできます。
|
•
|
つぎの例では、set および toString メソッドは StringBuffer クラスのインスタンスを第一引数とします。
|
>
|
module StringBuffer()
option object;
local buffer := Array( 1..0, datatype=integer[1] );
export set::static := proc( sb::StringBuffer, s::string, $ )
sb:-buffer := Array( convert( s, ':-bytes' ), datatype=integer[1] );
NULL;
end;
export toString::static := proc( sb::StringBuffer, $ )
convert( convert(sb:-buffer,list), ':-bytes' );
end;
export append::static := proc( sb::StringBuffer, s::string, $ )
local l, n;
l := convert( s, ':-bytes' );
n := :-numelems( sb:-buffer )+1;
sb:-buffer( n..n+:-numelems(l)-1 ) := Array(l);
NULL;
end;
end:
|
|
|
メソッドの呼び出し
|
|
|
エクスポートメソッドの呼び出し
|
|
•
|
オブジェクトによって export メソッドを呼び出すには、オブジェクトを引数として標準関数の呼び出し構文を使用します。関数コールの評価時に、Maple は指定した関数と同名のメソッドをエクスポートするオブジェクトについて引数を左から右に検索します。最初に見つかったメソッドと一致するオブジェクトのメソッドは与えられた引数を使って呼び出されます。
|
>
|
sb := Object(StringBuffer);
|
| (1) |
| (2) |
|
|
ローカルメソッドの呼び出し
|
|
•
|
Locals は、オブジェクトの宣言内で定義されたメソッドのみによってアクセス可能であるため、正しいプロシージャの関数コールを決定するためには通常のスコーピング規則で十分です。
|
|
|
インデックス付き関数コール内のオブジェクト
|
|
•
|
インデックス付きの関数コール (形式 func[index](args)) の作成時に Maple はオブジェクトと引数の一致についてインデックス (index) をチェックします。一致するオブジェクトがインデックス内にあった場合は、そのオブジェクトは引数内で一致するオブジェクトが見つかる前に使用されます。
|
|
|
|
ModuleCopy および ModuleApply を使用してオブジェクトファクトリーを作成
|
|
•
|
特殊な ModuleCopy および ModuleApply メソッドは、オブジェクトファクトリールーチンの実装用に組み合わせて使用します。ModuleCopy メソッドは、Object ルーチンが呼び出されて新規オブジェクトを作成するときの挙動を定義します。ModuleApply メソッドは、オブジェクト名が適用されるとき (つまり、関数コールとして使用されるとき) の挙動を定義します。
|
•
|
以下のメソッドを StringBuffer の宣言に追加すると、ModuleApply メソッドはファクトリールーチンになります。
|
>
|
export ModuleCopy::static := proc( sb::StringBuffer, proto::StringBuffer,
s::{string,StringBuffer}, $ )
if ( _npassed = 3 ) then
if ( type( s, ':-string' ) ) then
set( sb, s );
else
sb:-buffer := Array( s:-buffer );
NULL;
end;
else
sb:-buffer := Array( proto:-buffer );
NULL;
end;
end;
|
>
|
export ModuleApply::static := proc( )
Object( StringBuffer, _passed );
end;
|
•
|
ModuleCopy および ModuleApply を定義すると、StringBuffer を関数のように呼び出して新規インスタンスを作成できます。
|
| (3) |
>
|
set( sb2, "StringBuffer" );
|
| (4) |
>
|
sb3 := StringBuffer( "Another Buffer" );
|
| (5) |
| (6) |
>
|
sb4 := StringBuffer( sb3 );
|
| (7) |
| (8) |
|
|
演算子メソッド
|
|
•
|
Maple のオブジェクトは、演算子メソッドを実装できます。これらのメソッドは、オブジェクトと Maple の対応する演算子を使用するときに実行されます。StringBuffer に対する = 演算子は以下のように実装できます。
|
>
|
export `=`::static := proc( s1, s2, $ )
if ( _npassed = 1 ) then
return false;
end;
if ( not s1::{string,StringBuffer} or
not s2::{string,StringBuffer} ) then
return false;
end;
if ( s1::string ) then
evalb(s1 = toString( s2 ));
else
if ( s2::string ) then
evalb(toString( s1 ) = s2);
elif ( s1 = s2 ) then
true;
else
EqualEntries( s1:-buffer, s2:-buffer );
end;
end;
end;
|
>
|
sb1 := StringBuffer( "Hello" );
|
| (9) |
>
|
sb2 := StringBuffer( "Hello" );
|
| (10) |
>
|
sb3 := StringBuffer( "Goodbye" );
|
| (11) |
| (12) |
| (13) |
| (14) |
•
|
1 引数の場合はオブジェクトが NULL と比較される可能性をチェックすることに注意してください。
|
| (15) |
|
|
ビルトインルーチンの変更
|
|
•
|
オブジェクトは、同名のメソッドを定義することによりタイプ builtin のMaple ルーチンを変更できます。たとえば、以下のように StringBuffer は numelems 要素を実装できます。
|
>
|
export numelems::static := proc( sb::StringBuffer, s::string, $ )
:-numelems( sb:-buffer );
end;
|
•
|
最上位の numelems ルーチンを呼び出すと、:- 表記を使用して StringBuffer の numelems メソッドを微分する必要があります。これを行わないと StringBuffer numelems メソッドは無限再帰を発生することがあります。
|
•
|
numelems メソッドを定義すると、StringBuffer オブジェクトを他の Maple 構造と同様に numelems に渡すことができます。
|
>
|
numelems( [ 1, 2, 3 ] );
|
| (16) |
| (17) |
| (18) |
|
|
|
例
|
|
以下のコードは単一の宣言の例です。
>
|
module StringBuffer()
option object;
local buffer := Array( 1..0, datatype=integer[1] );
export ModuleCopy::static := proc( sb::StringBuffer, proto::StringBuffer,
s::{string,StringBuffer,':-list'( ':-integer[1]' )}, $ )
if ( _npassed = 3 ) then
if ( s::':-string' ) then
set( sb, s );
elif ( s::':-list'( ':-integer[1]' ) ) then
sb:-buffer := Array( s, datatype=integer[1] );
NULL;
else
sb:-buffer := Array( s:-buffer );
NULL;
end;
else
sb:-buffer := Array( proto:-buffer );
NULL;
end;
end;
export ModuleApply::static := proc( )
Object( StringBuffer, _passed );
end;
export numelems::static := proc( sb::StringBuffer, s::string, $ )
:-numelems( sb:-buffer );
end;
export `=`::static := proc( s1, s2, $ )
if ( _npassed = 1 ) then
return false;
end;
if ( not s1::{string,StringBuffer} or
not s2::{string,StringBuffer} ) then
return false;
end;
if ( s1::string ) then
evalb(s1 = toString( s2 ));
else
if ( s2::string ) then
evalb(toString( s1 ) = s2);
elif ( addressof(s1) = addressof(s2) ) then
true;
else
EqualEntries( s1:-buffer, s2:-buffer );
end;
end;
end;
export set::static := proc( sb::StringBuffer, s::string, $ )
sb:-buffer := Array( convert( s, ':-bytes' ), datatype=integer[1] );
NULL;
end;
export toString::static := proc( sb::StringBuffer, $ )
convert( convert(sb:-buffer,list), ':-bytes' );
end;
export append::static := proc( sb::StringBuffer, s::string, $ )
local l, n;
l := convert( s, ':-bytes' );
n := :-numelems( sb:-buffer )+1;
sb:-buffer( n..n+:-numelems(l)-1 ) := Array(l);
NULL;
end;
end;
|
|
|