vieweditattachhistorytopchangessearchhelp

第37回


■SqueakではじめるSmalltalk入門   第37回


 本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。今回は、再びプロトコルに話を戻し、コレクションの探索を続けます。

 まずは、ダブルディスパッチにからめて、飛ばしたadaptingプロトコルについてちょっとだけ。

 adaptingプロトコルには、前回登場した#adaptToCollection:andSend:の他に、#adaptToNumber:andSend:、#adaptToPoint:andSend:、#adaptToString:andSend:が定義されています。それぞれに対応するクラス(Number、Point、String)かそのサブクラスに属するインスタンスがレシーバとなる二項演算メッセージにおいて、その引数がコレクションだった場合の対処方法が記述されています。それぞれのメソッドの定義を見て、次に示した式の結果について予想がつくかどうかで、ダブルディスパッチを理解できているかを確認してみるのもよいでしょう。

4 * #(1 2 3)       " => #(4 8 12) "
(4 @ 5) * #(1 2 3) " => #(4@5 8@10 12@15) "
'456' * #(1 2 3)   " => #(456 912 1368) "


 adding、arithmeticは済んでいますね。comparingプロトコルは飛ばします。

 次のconvertingプロトコルには、コレクション間の相互変換のためのメソッドがまとめてあります。原則として単項メッセージセレクタで、asの後に変換したいコレクションクラス名が続きます。

#(2 2 3 4 1 4 2 1 4) asBag   " => a Bag(1 1 2 2 2 3 4 4 4) "
#(2 2 3 4 1 4 2 1 4) asSet   " => a Set(1 2 3 4) "
#(2 2 3 4 1 4 2 1 4) asOrderedCollection
              " => an OrderedCollection(2 2 3 4 1 4 2 1 4) "
#(2 2 3 4 1 4 2 1 4) asSortedCollection
                " => a SortedCollection(1 1 2 2 2 3 4 4 4) "
'smalltalk' asArray  " => #($s $m $a $l $l $t $a $l $k) "
'smalltalk' asBag    " => a Bag($k $l $l $l $m $a $a $s $t) "
'smalltalk' asSet    " => a Set($k $l $m $a $s $t) "
'smalltalk' asOrderedCollection
      " => an OrderedCollection($s $m $a $l $l $t $a $l $k) "
'smalltalk' asSortedCollection
        " => a SortedCollection($a $a $k $l $l $l $m $s $t) "


 変換と言っても、レシーバのクラスが変更されるわけではなく、レシーバをもとに、指定した種類のコレクションが新しく作られることに注意してください。

 ところで、新しくコレクションを作るには、この変換作業のほかに、作りたいコレクションが属するクラスに直接メッセージを送る方法もあります。オーソドックスには、まずnewを送信して空(から)のコレクションを作り、それに「add: anElement」などのメッセージを送って要素を追加してゆきます。

| collection |
collection _ OrderedCollection new.
collection add: 3; add: 2; add: 2; add: 1.
^ collection  " => an OrderedCollection(3 2 2 1) "

| collection |
collection _ Set new.
collection add: 3; add: 2; add: 2; add: 1.
^ collection  " => a Set(1 2 3) " "重複排除"

| collection |
collection _ SortedCollection new.
collection add: 3; add: 2; add: 2; add: 1.
^ collection  " => a SortedCollection(1 2 2 3) " "ソート済み"


 なおこの方法は、要素を増減させることができないコレクション(配列や文字列など)には使用できません。

Array new add: 3; add: 2; add: 2; add: 1  " => error "


 この種のコレクションの場合には、たんにnewするのではなく、「new: size」で必要なサイズのコレクションを用意してから、あらためて各要素を置き換える手続きが必要です。

| array |
array _ Array new: 4.
array at: 1 put: 3.
array at: 2 put: 2.
array at: 3 put: 2.
array at: 4 put: 1.
^ array   " => #(3 2 2 1) "


 要素が六つより少ないなら空のコレクションを作らずに、いきなり「with:anElement」、「with: element1 with: element2」、「with: element1 with:element2 with: element3」…というメッセージを送信して済ませることもできます。

OrderedCollection with: 3 with: 2 with: 2 with: 1
                     " => an OrderedCollection(3 2 2 1) "
Set with: 3 with: 2 with: 2 with: 1   " => a Set(1 2 3) "


 newしてから要素を追加するのと違って、この方法は配列や文字列にも使えます。

Array with: 3 with: 2 with: 2 with: 1   " => #(3 2 2 1) "
String with: $c with: $b with: $b with: $a  " => 'cbba' "


 要素が六つより多いときは、いったん要素を配列などに収めてから#withAll:で渡します。

OrderedCollection withAll: #(3 3 3 2 2 1 1 1 1)
                   " => an OrderedCollection(3 3 3 2 2 1 1 1 1) "
Set withAll: #(3 3 3 2 2 1 1 1 1)             " => a Set(1 2 3) "


 以上のようにクラスが受信を許すメッセージと、それによって起動されるメソッドについては、ブラウザの上段の左から二番目のペインの下にある、classボタンをクリックして閲覧モードを切り換えた後、instance creationプロトコルを選択することで、一覧したり、定義を見ることができます。

[fig.A]ブラウザでクラスプロトコルを閲覧しているところ。
Uploaded Image: 37a.png

このページを編集 (4492 bytes)


Congratulations! 以下の 1 ページから参照されています。

This page has been visited 830 times.