ActionScript3 Arrayの仕様

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

ActionScript3 Arrayの仕様

投稿記事 by MoNoQLoREATOR » 12年前

actionscript3においてArray型というのは特殊な型でして、今までコイツを魔法の箱だと認識していたのですが…実はそれほど特殊じゃないんじゃないかと思い始めました。
ふと思いついて、下記のコードを実行してみました。

CODE:

package 
{
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;
	
	/**
	 * ...
	 * @author MoNoQLoREATOR
	 */
	public class Main extends Sprite 
	{
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// entry point
			
			var arr:Array = new Array();
			var tf1:TextField = new TextField();
			tf1.text = "tf1";
			var tf2:TextField = new TextField();
			tf2.text = "tf2";
			arr.push(tf1);
			tf1 = tf2;
			trace( (arr[0] as TextField).text);
		}
		
	}
	
}
これは、Array型変数がtf1変数自体への参照を持つと仮定し、traceの部分で"tf2"が出力されることを期待するコードだったのですが、出力されたのは"tf1"でした。
これは、Array型変数がtf1が示す中身を持っているということを表しています。
よってtf1にインスタンスを代入し直してもそれはArray型変数には全く干渉しません。
と、いうことは、参照への参照を保持する変数を作るには、Object型変数をメンバに持つクラスを作ってそれを使って参照を管理するメンバ関数と、参照の参照を管理するメンバ関数を使い分けて…といったことをやらないといけないということに。(ActionScriptではプリミティブ型以外の全ての型がObject型を継承していることが保証されています)
多分今までのActionScript3プログラミングで詰まってた原因はこれですね…orz
なにはともあれ重要なことに気づいて良かったです。
最後に編集したユーザー MoNoQLoREATOR on 2012年11月06日(火) 03:06 [ 編集 1 回目 ]

ISLe
記事: 2650
登録日時: 14年前

Re: ActionScript3 Arrayの仕様

投稿記事 by ISLe » 12年前

C++以外のオブジェクト指向言語は、たいていネイティブ型(基本型・値型)とオブジェクト型(参照型)があってAS3と同じ仕様ですね。
入門書などでは最初にその辺がみっちり解説されているはずなのですが。

31行目を
tr1.text = "hoge";
とすれば、tr1.textと(arr[0] as TextField).textの両方が(同じインスタンスを参照しているので)"hoge"になります。

MoNoQLoREATORさんは変数の代入は変数そのものが代入されると思っているクチですかね。
そうなるとC/C++でコードを書けることが不思議なのですが、思い込みのはげしい方なのでしょうね。

参照というのはC/C++で言えばポインタのことです。
C++の参照とは異なるものです。
最後に編集したユーザー ISLe on 2012年11月06日(火) 16:52 [ 編集 2 回目 ]

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: ActionScript3 Arrayの仕様

投稿記事 by MoNoQLoREATOR » 12年前

いえいえ、単純に、Array型が魔法の箱だと思っていたのです。
Array型以外の型に関しては初めからちゃんと理解していましたよ。
どうして魔法の箱だと思うようになったのかは思い出せませんね。何かきっかけがあったような気がしないでもないのですが。
まあ、思い込みが激しいというのは明らかな事実なのですけれど。

ちなみに、私はC++のポインタ・参照のシステムよりもActionScriptやその他諸々の言語で採用されている参照のシステムの方が好きです。
C++のポインタは実体参照する際にいちいち*をつけないといけないし、"ポインタのポインタ"の場合は
(*pointer)[0]
このようにかっこをつけてあげないといけないし、面倒くさいんですよ。
私の場合はアドレス参照よりも実体参照の方が圧倒的に多いので、アドレス参照の時に*をつけるようにしてほしかったなと思い、あれ?てことはもういっそのこと普通の変数として扱えるようにして、アドレス参照したい時は普通の変数と同じように&をつけるようにすればいいんじゃないの?っていう思考に辿り着きまして、結局あの結論を導き出したわけですよ(ここの『○ポインタ、参照、コネクション?』参照)。
つまり、ポインタなんか廃止して、途中で参照先を変えられる参照を代わりに用意しましょうってことです。
正にActionScript風の参照ですね。
ちなみに、C++の参照はそれはそれで好きですよ。
参照先がずっと同じことが保証されていますから。
しかしC++からポインタを取ってしまうと困るのが配列ですね。配列は半分ポインタみたいなもんですからね。
まあ、std::vectorを使えば解決するんですけどね。あれは配列をまるごと値渡しすることも簡単にできますし。
要は、「配列型」というのを作るべきなんですよ。
参照と同じように、型の右に [] をつければそれは配列変数になるとかいう風にすればいいんですよ。
int[] intarr = {0,1,2};
C#みたいな感じですね。
たしかに、若干スピードは落ちるかもしれませんが。
最後に編集したユーザー MoNoQLoREATOR on 2012年11月06日(火) 17:23 [ 編集 1 回目 ]

アバター
h2so5
副管理人
記事: 2212
登録日時: 14年前

Re: ActionScript3 Arrayの仕様

投稿記事 by h2so5 » 12年前

MoNoQLoREATOR さんが書きました: C++のポインタは実体参照する際にいちいち*をつけないといけないし、"ポインタのポインタ"の場合は
(*pointer)[0]
このようにかっこをつけてあげないといけないし、面倒くさいんですよ。
そんなに面倒なら一時変数を使って

CODE:

auto& foo = *pointer;
みたいにして foo 経由でアクセスすればいいんじゃないかと思いますが。

ISLe
記事: 2650
登録日時: 14年前

Re: ActionScript3 Arrayの仕様

投稿記事 by ISLe » 12年前

C/C++は唯一ポインタに対して演算できることが特徴なわけですが、それが無くなるといろんな機械を動かせなくなりますよ。
ハードウェアのI/O周りを直接叩くプログラムを作ってみると分かると思いますが。

はっきり言ってPCしか使わないひとは他の言語を使えば良いのですよ。
C/C++言語そのものをどんどんPCだけに都合の良いように変えていくとそのうちたいへんなことになるんじゃないですかね。

仕事でゲームを作っているとポインタのポインタのポインタくらいはふつうに出てくるのですが、かといってポインタのポインタを直接参照するようなコードを書いたことはありません。
どこのコードも間接参照いっこするだけです。
ポインタのポインタを記述するのがめんどうくさいのは分かりますが、それはどんなときで、どのくらいの頻度で起きることなのでしょうか。
仮に、しばらくぶりにポインタのポインタを使おうと思ったらめんどうくさかった、というようなことであればそれは注意喚起となりますからむしろメリットだと思います。

アバター
MoNoQLoREATOR
記事: 284
登録日時: 14年前
住所: 東京

Re: ActionScript3 Arrayの仕様

投稿記事 by MoNoQLoREATOR » 12年前

はい。お二方が仰るように参照で一度ラッピングしてから使用しています。
もし「途中で参照先を変えられる"参照"」があればこの作業からも解放されます。
あ。勢いで「廃止する」と書いてしまいましたが、別に廃止する必要はないですね。「途中で参照先を変えられる"参照"」さえあれば何も不満なことはありません。もちろん現行の"参照"も廃止すべきではないと思っています。
「途中で参照先を変えられる"参照"」があるのであれば、私はポインタを使わなくなるだろうということです。

たしかにポインタのポインタを使ったことはほとんど無いですね。
(*pointer)[0]
こんな風に書かなければならないことが非常に嫌だったということを鮮明に覚えていたので、例として挙げておきました。
現在は先にも記述した通り参照でラッピングしてから使用しています。