ObjectSquare [1999 年 4 月号]

[Happy Squeaking!!]


5.Squeak演習: インターセッション

5.5 インターセッション応用

Interfaceのメタモデルの追加 つづき


次に機能の実装に入ります。今回はあくまでもメタモデル追加の例ですので、あまり本格的な実装までには立ち入りません。

まずはあるインスタンスが、特定のInterfaceに対応しているかを確かめる操作を作ってみましょう。

以下のような実装になります。

(Interface >> actionsカテゴリ)
by: anObject
        self operationList do:[ :each | (anObject respondsTo: each) ifFalse:[^self 
error:anObject name , ' does not support ', self name, ' interface']].
        ^anObject

新たにでてきたのはdo:とerror: です。順番に説明していきましょう。

集合オブジェクトの要素を一つ一つ取り出したいときにdo:を使うことができます。
例えば、#('this' 'is' 'Smalltalk') という配列があり、それぞれをTranscriptに改行させて表示したいとします。この場合do:を使って、
#('this' 'is' 'Smalltalk') do:[:each | Transcript cr; show: each].
と書くことができます。

eachの中には、要素ひとつひとつが順番に入っていきます。名前はeachである必要はありませんが、ブロック内部でのみ使われる変数として、ブロックの先頭で宣言しなければなりません。例の場合は[ :each | がその部分になります。
SmallTip: 集合オブジェクトの要素を順番に取り出すときにはdo:を用いる

次は、error: です。これは単純で、エラーノーティファイアを出し、処理を中止したいときに使用されます。

SmallTip:エラーノーティファイアを出し、処理を中止したいときに error: を用いる

では改めてコードを見ます。

by: anObject
        self operationList do:[ :each | (anObject respondsTo: each) ifFalse:[^self 
error: anObject name , ' does not support ', self name, ' interface']].
        ^anObject

Interface自身の持つ操作名の集合operationListの要素をdo:により一つ一つ取り出し、それぞれの操作が、引数として与えられた anObjectによって答えることができるかをrespondsTo:によって調べています。答えることのできない操作が有った場合には、エラーノーティファイアを出して処理を中止します。全ての操作に答えられることがわかった場合は、引数として来たanObjectをそのまま返します。

使い方は以下のようになります。

"inspect it"
| accIf acc |
accIf := Interface name: #IAccount operationList: #(#deposit: #getBalance 
#withdraw:). "IAccount インターフェース生成"
acc := Account new. "Accountインスタンス生成"
(accIf by: acc) deposit: 1000. "AccountインスタンスをIAccountに適合して実行"

Accountインスタンスは、きちんとIAccountの操作名の集合を実装していますのでエラーは出ず、正常に実行されます。


IAccountを実装したAccountインスタンスのdeposit:の実行結果

IAccountの規定する操作を実装していないOrderedCollectionなどを使うとエラーになります。

| accIf ord |
accIf := Interface name: #IAccount operationList: #(#deposit: #getBalance 
#withdraw:).
ord := OrderedCollection new.
(accIf by: ord) deposit: 1000.

拡大図(GIF, 3KB)
IAccountを実装していないためノーティファイアが開く

本来は、ブラウザ上のクラスの定義用テンプレートをカスタマイズして、instanceVariableNames: などの変数定義の他に、supportsInferfaces: と記入できるようにし、"accept"時に、そのクラス(のインスタンス)がサポートするInterfaceを調べ、実装していない場合はノーティファイアを出すといった具合にするのが理想的です。あくまでサンプルですのでこのような簡易な実装にとどめています。

更につづく


© 1999-2001 OGIS-RI Co., Ltd.

Prev.

Index

Next