[AS]クロージャのイイ感じの使用用途

クロージャとは、functionの中にfunctionを書くような書き方。(だと思う)
フレームに書いたらこんな感じ。

//フレームアクション
function test(){
	var func:Function  = new Function();
	func = function(){
		trace("func内this : " + this);//出力:func内this : [object global]
	}
	trace("test内this : " + this);//出力:test内this : [object MainTimeline]
	func();
}
test();

これ使うと関数内のthisが何を示すか混乱するのよ。(私にとっては、ね)。
なので、あまり使わないようにしてたけど、便利そうな使い方を教わったのでご紹介。

たとえば、フェードイン処理とフェードアウト処理について。
以下のように書くことですっきりまとまる。

package {
	public class Main extends Sprite {
		//関数をインスタンス化しておく
		private var fader:Function = new Function();
		
		public function fadeIn( speed:Number ) : void {
			//※addEventListenerされてない状態をremoveしてもエラーにはならない
			removeEventListener( Event.ENTER_FRAME, fader )
			//リスナー関数をaddEventListenerと同じ位置にかく
			//fader関数の中身を設定
			fader = function( e:Event ) : void {
				alpha += speed;
				if( alpha >= 1 ) {
					removeEventListener( Event.ENTER_FRAME, fader )
				}
			}
			addEventListener( Event.ENTER_FRAME, fader )
		}
		
		public function fadeOut( speed:Number ) : void {
			//※addEventListenerされてない状態をremoveしてもエラーにはならない
			removeEventListener( Event.ENTER_FRAME, fader )
			//fader関数の中身を設定
			fader = function( e:Event ) : void {
				alpha -= speed;
				if( alpha <= 0 ) {
					removeEventListener( Event.ENTER_FRAME, fader )
				}
			}
			addEventListener( Event.ENTER_FRAME, fader )
		}
	}
}

ポイントのひとつは、フェードインもアウトも同じfaderという関数を使っているところ。
インとアウトが同時実行されることはない。(remove処理が確実に行われる)
同時に実行させる必要があれば、新しいFunctionインスタンスを作ればよい。
あと、Functionインスタンスがnullでなければ、addEventListenerしてない状態で、removeEventListenerしてもエラーにはならない。

この書き方なら、フェード処理をもっと細かく設定したい場合も以下のようにすっきりかける。

//フェードイン関数のみ抽出
public function fadeIn( speed:Number ) : void
{
	removeEventListener( Event.ENTER_FRAME, fader )
	fader = function( e:Event ) : void
	{
		alpha += speed;
		//追加:アルファが0.5以上になったら、スピードを半分にする
		if( alpha >= 0.5) {
			removeEventListener( Event.ENTER_FRAME, fader )
			fader = function( e:Event ) : void
			{
				alpha += speed/2
				if( alpha >= 1) {
					removeEventListener( Event.ENTER_FRAME, fader )
				}
			}
			addEventListener( Event.ENTER_FRAME, fader )
		}
	}
	addEventListener( Event.ENTER_FRAME, fader )
}

[AS](MCの)参照渡しと、配列への格納への違い

メモリ管理でつまづいている、ちょっと挙動がわからない。

やりたいことはこんな感じ。

var mc0:MovieClip = new MovieClip();
addChild(mc0);
var array:Array = []
array.push(mc0);
var mc1 = array[0]

//↓で表示リストから消えるのは無問題
removeChild(mc1);
//↓だとmc0分のメモリは消えないっぽい。
mc1=null;
//↓だとmc0分のメモリは消えるっぽい。
array[0] = null;

参照先を操作すれば、表示リストからは消せる。
でも、メモリを開放できないのがなんだか気持ち悪い。
参照で渡した場合、参照先をnullにしても、参照元はnullにならないってこと?
配列に格納するのも参照渡しと同じ感覚だと思っていたけど、違うってこと?
このあたりは今度えらい先生と会う機会があるときに教えてもらおう・・・

[追記]
コメントにて教えて頂きました。
参照で渡した場合、参照先をnullにしても、参照元はnullにならない、でOK。
参照先との関係が切れるだけ、ということだそうです。

[AS]overrideする場合は、元の関数とパラメータを同じにすること

関数をoverrideする場合は、元の関数とパラメータを全て同じにする必要があるらしい。
以前、インターフェースでは戻り値必須という記事を書いたけど、overrideもそんな感じらしい。

↓この関数をoverrideするには・・・

protected function testFunc(){}

↓こんな感じになる。

protected override function testFunc(){}
//↓これだとNG(voidがあるから)
//protected override function testFunc():void{}

またこういう場合は、

protected function testFunc():void{}

こんな感じ

protected override function testFunc():void{}
//↓これだとNG(voidがないから)
//protected override function testFunc(){}

注意が必要なのは、戻り値のvoid。
あってもなくても意味一緒じゃね?と思ってもFlash上では一緒とは判断してくれない模様。
正確にコーディングしないと。。。

参考サイト
desginのFlash:[エラー!!][AS3]1023: オーバーライドに対応していません。

[AS]Flickrの画像のBitmapDataを弄る際のセキュリティ解除方法

Flickrの画像を読み込み、bimapdataを弄ろうとすると、以下のように怒られる。

SecurityError: Error #2122: セキュリティサンドボックス侵害 : BitmapData.draw:http://393.bz/test/New.swf は http://farm4.static.flickr.com/3315/3667944681_06e506542e.jpg にアクセスできません。ポリシーファイルが必要ですが、このメディアがロードされたとき、checkPolicyFile フラグが設定されませんでした。
at flash.display::BitmapData/draw()
at NewClass/drawImage()

以下のおまじないを記述すれば大丈夫。

Security.loadPolicyFile("http://api.flickr.com/crossdomain.xml");
Security.loadPolicyFile("http://farm1.static.flickr.com/crossdomain.xml");
Security.loadPolicyFile("http://farm2.static.flickr.com/crossdomain.xml");
Security.loadPolicyFile("http://farm3.static.flickr.com/crossdomain.xml");
Security.loadPolicyFile("http://farm4.static.flickr.com/crossdomain.xml");

[AS]配列の中身全部をtraceする

toString()で楽勝でした。

var num:Number = 100;
var array:Array = ["a","b","c",num]
trace(array.toString()) //出力:a,b,c,100

[AS][自分用]ActionScript3.0デザインパターンの読書メモ(8)
-カプセル化

カプセル化とは、
1.パブリックなプロパティは使わない
2.外部クラスのオブジェクトを参照しない。(そのクラスの引数を経由した参照は除く)

よくわからんけど、プロパティ値を変更するときは直接変更できないようにして(privateにする)、
パブリックなメソッドを用意してそれを使って内部のプロパティを変更するような仕組みを作るといいらしい。
2.については引数を使わずに外部クラスを参照する方法が浮かばないのだが。

[FD]{の前の改行位置を自分流に変更する

FlashDevelopだと自動で生成してくれる構文が、デフォルトだと、{前に改行される。
こんな感じ

package  
{
	public class ClockData 
	{
		public function ClockData() 
		{
			
		}
	}
}

まぁ好みの問題で、{前は改行してくれない方が良いという場合。
(いわゆる私の場合)
これは設定ファイルを書き換えればコントロール可能。
Tool→ApplicationFilesで開いたフォルダ内のファイルを弄る。
たとえば、Templatesフォルダ内のProject→AS3Project内のClass.as.fdtを開いてみると、改行が入る場所に、
$(CSLB)という文字列があるのでこれを削除すれば改行されなくなる。
ほかにも適宜ファイルの$(CSLB)を消せば改行部分を削除可能。

※一点だけ、わかりにくかった場所・・・
ctrl+shift+1で生成させる部分の改行設定は、
Data→ASCompletion→Generator.txtにて設定可能。

[AS][自分用]ActionScript3.0デザインパターンの読書メモ(7)
-プロキシパターン

プログラムのタスク処理における一般的なやりかた。
他のオブジェクトへのアクセスを提供するためのクラス。
(他のオブジェクト:AS、img、xml、flv、FMS等)
最初にオブジェクトを全部作ってしまうのではなく、必要なときに作ろうという考え方。

仮想プロキシとリモートプロキシの2種類ある。

仮想プロキシ
Loaderクラスがまさにそれ。
プロキシという考え方があるから、画像を読み込みの際、読み込みが完了する前にLoaderのプロパティとか変更できるということらしい。

こんな感じか

//インスタンス生成
var loader:Loader = new Loader();
//loaderインスタンスにはまだ中身は無いけどプロパティとか設定しておく
loader.x = 100;
loader.y = 200;
loader.alpha = 0.5;
//表示リストに追加しちゃっておいても良い
this.addChild(loader);
//そして以下、欲しいときにload()メソッドを実行すればいい、みたいな感じ?

他に仮想プロキシの役割として、ゆるいシリアル化
ゆるいシリアル化の例(XMLの項目を
→硬いシリアル化:xmlを最初に全部要素、属性ごとに配列とかに割り振っちゃう
→ゆるいシリアル化:必要なときに応じて、都度xmlを取り出して使う

リモートプロキシ
対象がネットワーク先になるような感じ。
たとえばflikrAPIをたたいてAPIのメソッドに従った画像ひっぱってくるときの場合、みたいな

[AS]インターフェイスで関数を定義する際、および実装する際は戻り値が必須

インターフェイスで関数を定義する際は戻り値が必須らしい。
(戻り値がない場合も必ずvoidを書かないと駄目っぽい)

たとえばこれだとエラーになった。

package  {
	public interface TestInterface {
		
		//↓戻り値のvoidを省略すると駄目っぽい
		function testFunc1();
		//↓これはOK
		function testFunc2():void;
		function testFunc3():Boolean;
	}
}

また実装の際にもInterfaceで定義された関数を記述する際もvoidの記述が必須。
(省略したらエラーになった)

たとえばこんな感じ。

package  {
	public class Jissou implements TestInterface{
		
		public function Jissou() {
			
		}
		//↓voidを省略するとエラー
		public function testFunc1() {
			trace("testFunc1");
		}
		//これならOK
		public function testFunc2():void {
			trace("testFunc2");
		}
		public function testFunc3():Boolean {
			var bol:Boolean = false;
			return bol;
		}
	}
}

[AS][自分用]ActionScript3.0デザインパターンの読書メモ(5)
-シングルトンパターン

シングルトンのルール
・(シングルトンインスタンスは)プライベートなstaticなプロパティに保持
・(シングルトンインスタンスに)アクセスするにはパブリックなメソッドを使う。(インスタンスが無い場合は生成)

汎用的なシングルトンパターン

package  {
	public class Singleton {
		
		//Singletonインスタンスを保持
		static private var _instance:Settings;
		
		//他のオブジェクトからnew Singleton()では作らせないようにする
		public function Singleton(enforcer:SingletonEnforcer) {
		}
		
		//インスタンス作成はこのメソッドで
		public function getInstance():Settings {
			//一回目はインスタンスを作る
			if (Settings._instance == null){
				Settings._instance = new Settings(new SingletonEnforcer));
				
			}
			//保持しているインスタンスを返す
			return Settings._instance;
		}
	}
}
//new Singletonさせないためのクラス
class SingletonEnforcer{}