Elephant Communicationsの制作スタッフが日々気になったことをお届けするブログです。

« スイーツ大将 | メイン | [Embed(source="xxx")]のなぞ »

火曜日, 5 20, 2008

どうにかこうにか第二回を書くことができました。 今回も広く浅くお送りしたいと思います(興味を持つきっかけになってもらえたら十分ですね)。 実際にオブジェクト指向のサンプルがでてくるまではまだ先になるかと思いますけど、 初心者によるOOPの第二回です。

前回のネタで グローバル変数とローカル変数の有効範囲(スコープ)の違いについて 書かせてもらったのですが、基本はあんな感じです (もっと奥は深いので、いろいろと調べてみてください)。

今回は仮引数について軽く触れてみたいと思います。いちおう動作確認はFlash上でしてありますが、何か間違ったことを書いていたらご指摘ください。

仮引数とは?

仮引数というのは、関数に渡された値のことです。 以下の例におけるstrnumが仮引数になります。

function myFn(str:String, num:Number) {
	// statemente;
}

この仮引数というものは、基本的にはローカル変数になります。 つまり、var宣言をしなくてもスコープはローカルに設定されます。 ※ただしここまでだけでは半分ウソです。後ほど説明します。

仮引数のスコープを調べる

同じ名前を持つ変数であっても、スコープが違う場合はまったく別の変数として扱われます。

// グローバル領域で変数を宣言
var str:String = "GLOBAL";

// 関数の定義
function myFn2(str:String) {
    trace(str);				// 仮引数を出力
    str = "TEST";			// 変数を書き換える
}

// 関数を実行
myFn2("LOCAL");

// グローバル変数strが関数内で書き換えられたかチェック
trace(str);

このサンプルを実行してみると、グローバル変数は 関数内で書き換えられていないことがわかります。 つまり、スコープが違うので同じ変数名を持っていたとしても まったく別の変数として取り扱われているということになります。

値渡しと参照渡し

さきほどから、仮引数は引数で渡された変数と別の変数になると書いていますが、 実はもう少し複雑です。今度は引数に配列を渡してみます。

// 配列を用意する
var fruits:Array = ["バナナ", "リンゴ", "モモ"];

// 関数を定義
function myFn3(ary:Array) {
	ary[0] = "ゴリラ";		// 配列の一番最初にゴリラを代入
}

// 関数に配列を渡す
myFn3(fruits);

// 配列をtraceしてみる
for(var i=0; i<fruits.length; i++){
	trace(fruits[i]);
}

「バナナ」が「ゴリラ」に置き換わってしまいました… 先ほどのmyFn2の例を経て考えるとこれはおかしいです。

実は仮引数に渡された値はローカル扱いになると書きましたが、 それは値渡しの場合に限ります。 値渡しとは、その値を別の変数へコピーしてやる引数の渡し方です。 この場合は仮引数はローカル扱いとなり、 スコープが違う場合はまったく別の変数として扱う必要があります。 数値を引数に渡す場合は、値渡しです。

参照渡しの場合は、その変数が持つ ポインタのようなものをコピーして渡してやります。 「ポインタのようなもの」というのは、コンピュータ内で確保されたメモリ領域のようなものです。C言語ではポインタという概念が重要になってくるみたいですが、少なくともActionScriptでは意識しなくても大丈夫なので、「ポインタのようなもの」と書きましたが。

つまり参照渡しの仕組みとしては、 変数がどのメモリ領域を参照すればいいかという情報をやりとりしているだけで、 そのメモリに格納されている値を実際に渡しているわけではありません。 今回の例のように配列を引数に渡す場合は参照渡しとなります。 参照渡しになるケース、以下の2つを渡す場合は参照渡しと 覚えておけば大丈夫だと思います。

  • オブジェクトを渡すとき
  • 配列を渡すとき

最後にオブジェクトを渡すサンプルも書いてみます。

// オブジェクトを生成
var obj:Object = new Object();

// オブジェクトのプロパティを設定
obj.val = "オブジェクトを参照しています";

// 関数を定義
function myFn4(argObj:Object) {
	// オブジェクトのプロパティを上書き
	argObj.val = "関数内で値が上書きされました";
}

// 関数へオブジェクトを渡す
myFn4(obj);

// オブジェクトのプロパティをtrace
trace(obj.val);

実はもっとシンプルに伝えられるハズなんですが、文章にするととんでもなく長くなる&わかりづらいですね…今回の参照(ポインタ)の概念に少し触れている本を紹介しておきます。

参考文献:オブジェクト指向でなぜつくるのか
日経BP企画 平澤 章 (著)

トラックバック

このエントリーのトラックバックURL:
http://lab.elephant-com.co.jp/cgi-bin/mt/mt-tb.cgi/93

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)