ActionScript 3.0で始めるオブジェクト指向スクリプティング

第32回Dictionaryクラスを使う

今回は、新たに「Dictionaryクラス」をお題にする。Dictionaryクラスには、独自のメソッドとしてコンストラクタしか備わっていない。しかも、[ヘルプ]を読んでも、何をするクラスなのか要領を得ない。しかし、実はかなり使いでのあるクラスなのだ。

インスタンス同士を関連づける

練習のサンプルには、前回のロールオーバーのネタを使う。ステージの端にサムネイル画像を並べて、それらにロールオーバーしたとき、対応する大きい画像の表示を切替えるムービーだ(図1)。

図1 サムネイルにロールオーバーすると対応する画像が切替わる
図1 サムネイルにロールオーバーすると対応する画像が切替わる
画像

第31回「マウスのロールオーバー」の2ページからダウンロードできる、スクリプト2のサンプルファイルのスクリプトに手を加える(図2)。今回考えるのは、サムネイルと画像のインスタンスをどう関連づけるかである。

図2 メインタイムラインに書かれたフレームアクション
図2 メインタイムラインに書かれたフレームアクション

前回のスクリプト2は、以下に抜粋したように、サムネイルのインスタンス(button0_mc~button2_mc)に同じ名前の変数(show_mc)を設定し、それぞれに対応する画像のインスタンス(my0_mc~my2_mc)を納めた。そのうえで、リスナー関数(xShow())が受取ったイベントオブジェクトから、イベントリスナーの登録された(Event.currentTargetプロパティの)サムネイルのインスタンスを取出し、その変数が参照する画像のインスタンスを操作した。

button0_mc.addEventListener(MouseEvent.ROLL_OVER, xShow);
button1_mc.addEventListener(MouseEvent.ROLL_OVER, xShow);
button2_mc.addEventListener(MouseEvent.ROLL_OVER, xShow);
button0_mc.show_mc = my0_mc;
button1_mc.show_mc = my1_mc;
button2_mc.show_mc = my2_mc;
// ...[中略]...
function xShow(eventObject):void {
  var my_mc:MovieClip = eventObject.currentTarget as MovieClip;
  var show_mc:MovieClip = my_mc.show_mc;
  // ...[中略]...
  show_mc.visible = true;
  // ...[中略]...
}

今回は少し考え方を変えて、画像のインスタンス(my0_mc~my2_mc)はひとつにまとめて、サムネイルのインスタンス(button0_mc~button2_mc)をキーとして設定する。そのキーをもとに、対応する画像を取出そうということだ。

これまで学んだ方法でいえば、Objectクラスが使えるだろう(第19回Objectクラスと静的メソッドの定義)。Objectインスタンスにサムネイルの各インスタンス(button0_mc~button2_mc)名をプロパティ名として、対応する画像のインスタンス(my0_mc~my2_mc)の参照を納めればよい(スクリプト1)。

var showList:Object = new Object();  
// ...[中略]...
showList.button0_mc = my0_mc;
showList.button1_mc = my1_mc;
showList.button2_mc = my2_mc;
// ...[中略]...
function xShow(eventObject):void {
  var show_mc:MovieClip = showList[eventObject.currentTarget.name];
スクリプト1 Objectに設定した各インスタンス名のプロパティに対応するインスタンスを納める
// タイムライン: メイン
// MovieClipインスタンス
// サムネイル: thum0_mc~thum2_mc
// 表示画像: my0_mc~my2_mc
// フレームアクション
var glow:GlowFilter = new GlowFilter(0x000033);
var dropShadow:DropShadowFilter = new DropShadowFilter();
var filters_array:Array = [glow, dropShadow];
var showList:Object = new Object();   // 新規Objectインスタンスの生成
button0_mc.addEventListener(MouseEvent.ROLL_OVER, xShow);
button1_mc.addEventListener(MouseEvent.ROLL_OVER, xShow);
button2_mc.addEventListener(MouseEvent.ROLL_OVER, xShow);
// インスタンス名のプロパティに対応するインスタンスの参照を格納
showList.button0_mc = my0_mc;
showList.button1_mc = my1_mc;
showList.button2_mc = my2_mc;
xClearAll();
function xShow(eventObject):void {
  // Objectからインスタンス名のプロパティに納められた対応する参照を得る
  var show_mc:MovieClip = showList[eventObject.currentTarget.name];
  xClearAll();
  show_mc.visible = true;
  show_mc.filters = filters_array;
}
function xClearAll():void {
  my0_mc.visible = false;
  my1_mc.visible = false;
  my2_mc.visible = false;
  my0_mc.filters = [];
  my1_mc.filters = [];
  my2_mc.filters = [];
}

リスナー関数xShow()は、受取ったイベントオブジェクトのEvent.currentTargetプロパティからDisplayObject.nameプロパティでサムネイルのインスタンス名の文字列を得ている。そのうえで、配列アクセス演算子[]によりObjectインスタンスから、対応する画像のインスタンスを取出した(変数show_mcに格納)。

もっとも前回の最後に、DisplayObject.nameプロパティは、trace()関数で[出力]してインスタンス名を確かめる以外には、あまり使い勝手はよくない」と述べた(※1)。そして、⁠ActionScript 3.0では、できるだけインスタンスの参照を使う仕組みにする方がよい」とも申し上げた。その「仕組み」をつくるひとつの手がDictionaryクラスの利用だ。

Dictionaryクラスは参照をキーにできる

Dictionaryクラスは、きわめてあっさりした組立てだ。何しろ、独自のプロパティはなく、メソッドもコンストラクタしかない(図3)。流行りの言回しなら「草食系」クラスといったところだろう。では、中身もわかりやすいかというと、[ヘルプ]の[Dictionary]クラスにはこんな説明がされている。おそらく、これで理解できる人は少ないだろう。

Dictionaryクラスでは、プロパティの動的なコレクションを作成し、キーの比較に厳密な等式(===)を使用できます。オブジェクトがキーとして使用されている場合は、オブジェクトの識別子を使用してオブジェクトを検索し、オブジェクトのtoString()を呼び出して返される値は使用されません。

図3 Dictionaryクラスのプロパティとメソッド
図3 Dictionaryクラスのプロパティとメソッド

文法について詳しくは、筆者のサイトにDictionary()コンストラクタというリファレンスを掲載しているのでお読みいただきたい。ただ、押さえておくべきことはふたつだ。

第1に、Dictionaryクラスの使い途は、配列(Array)やObjectクラスと同じ複数の値を納める「容れ物」である。第2に、 Dictionaryクラスの特長として、キーにオブジェクトの参照を用いることができる。その他にキーとしては、配列と同じ整数インデックスも指定できるし、もちろんObjectクラスを継承しているので文字列の識別子も使える。しかし、参照そのものをキーにできることが大きな利点といえる。

スクリプト1を書替えて、ObjectでなくDictionaryインスタンスを使った処理にしたのが以下のスクリプト2だ。

スクリプト2 Dictionaryにインスタンスの参照をキーにして対応するインスタンスを納める
// タイムライン: メイン
// MovieClipインスタンス
// サムネイル: thum0_mc~thum2_mc
// 表示画像: my0_mc~my2_mc
// フレームアクション
var glow:GlowFilter = new GlowFilter(0x000033);
var dropShadow:DropShadowFilter = new DropShadowFilter();
var filters_array:Array = [glow, dropShadow];
var showList:Dictionary = new Dictionary();   // 新規Dictionaryインスタンスの生成
button0_mc.addEventListener(MouseEvent.ROLL_OVER, xShow);
button1_mc.addEventListener(MouseEvent.ROLL_OVER, xShow);
button2_mc.addEventListener(MouseEvent.ROLL_OVER, xShow);
// インスタンスの参照をキーにして対応するインスタンスを格納
showList[button0_mc] = my0_mc;
showList[button1_mc] = my1_mc;
showList[button2_mc] = my2_mc;
xClearAll();
function xShow(eventObject):void {
  // Dictionaryからインスタンスの参照をキーにして対応するインスタンスを得る
  var show_mc:MovieClip = showList[eventObject.currentTarget];
  xClearAll();
  show_mc.visible = true;
  show_mc.filters = filters_array;
}
function xClearAll():void {
  my0_mc.visible = false;
  my1_mc.visible = false;
  my2_mc.visible = false;
  my0_mc.filters = [];
  my1_mc.filters = [];
  my2_mc.filters = [];
}

サムネイルのインスタンス(button0_mc~button2_mc)の参照をキーにするので、Dictionaryインスタンス(変数showList)に配列アクセス演算子[]で文字列でなくインスタンスそのものを指定し、対応する画像のインスタンス(my0_mc~my2_mc)を納めている。また、リスナー関数xShow()でも、イベントオブジェクトのEvent.currentTargetプロパティで得られた参照をそのままDictionaryインスタンスのキーに指定して、対応する画像のインスタンスが得られる。

var showList:Dictionary = new Dictionary();
// ...[中略]...
showList[button0_mc] = my0_mc;
showList[button1_mc] = my1_mc;
showList[button2_mc] = my2_mc;
// ...[中略]...
function xShow(eventObject):void {
  var show_mc:MovieClip = showList[eventObject.currentTarget];

今回のサンプルムービーは、サムネイルのインスタンスを予めタイムラインに置いてインスタンス名をつけておいたので、スクリプト1と2とでステートメント数が変わらない。けれど、インスタンスを動的に生成するときには、Dictionaryクラスで扱えば、わざわざインスタンス名をつけなくて済む(※2)。前回も述べたとおり、⁠ActionScript 3.0では、できるだけインスタンスの参照を使う仕組みにする」ことがお勧めといえる。

さて、次回からは、Flash Player 10の3次元空間の扱いに入りたい。

今回解説した次のサンプルファイルがダウンロードできます。

おすすめ記事

記事・ニュース一覧