ApplicationDomain

  • 2010 年 4月 18 日
  • kosuke

最近のFlashはサイトは1つのプロジェクトを分業して複数人で開発することが多くなってきた。大規模なサイトを構築・運営するには一人の開発者が全てまかなえるわけもなく当然な話でもある。

そうなると問題になりそうなことがクラス名の衝突。実際、AS2のフルフラッシュサイトでは問題になったことも度々あった。
クラスベースで開発することが多いAS3では、親と子側のSWFで開発者が違うと同名のクラスがあって思うように動かないなんてことがますます増えそうだ。

そこで同名クラスの問題を回避するApplicationDomainの使い方を記録しておく。
ApplicationDomainの指定で同名クラスであっても親と子のクラスを分離できる。

2つのSWFがありどちらもドキュメントクラスがIndexだとします。
ただし、このIndexは別の開発者が作った別のクラス。そこで、

1) Index1.swf = Aさんが作ったswfで、Aさんが作ったIndexドキュメントクラスを持つ。
2) Index2.swf = Bさんが作ったswfで、Bさんが作ったIndexドキュメントクラスを持つ。
3) Index1.swfは、子としてIndex2.swfを読み込む。

とします。

で、Aさんが作ったindex1.swfのIndexクラスは、

package{
	import flash.display.*;
	public class Index extends Sprite{
		public function Index(){
			trace( "Aさん" );
		}
	}
}

「Aさん」と出力する。

かたや、Bさんが作ったindex2.swfのIndexクラスは、

package{
	import flash.display.*;
	public class Index extends Sprite{
		public function Index(){
			trace( "Bさん" );
		}
	}
}

「Bさん」と出力する。この二つもちろん単体では問題なく動きます。

しかし、Aさんの作ったIndexでBさんのindex2.swfを読み込むと

package{
	import flash.display.*;
	public class Index extends Sprite{
		public function Index(){
			trace( "Aさん" );
			var loader:Loader	= new Loader();
			loader.load( new URLRequest( "Index2.swf" ) );
		}
	}
}

期待に反して「Aさん」が出力され続ける。

読み込まれたBさんのIndexは、AさんのIndexクラスと同名の為、親側のAさんのIndexクラスと区別がつかず、AさんのIndexクラスを実行し続けてしまいます。なんにも取り決めをせず、別々に作ったら起きそうなエラーでしょ?
こんな時の為にApplicationDomainがあります。

AさんのIndexで、LoaderContextでアプリケーションドメインを分離して読み込むと、

package{
	import flash.display.*;
	public class Index extends Sprite{
		public function Index(){
			trace( "Aさん" );
			var context:LoaderContext	= new LoaderContext( false, new ApplicationDomain( null ) );
			var loader:Loader	= new Loader();
			loader.load( new URLRequest( "Index2.swf" ), context );
		}
	}
}

今度は正しく「Aさん」「Bさん」と出力されました。

ApplicationDomainはクラスを分離しているだけで、Index2.swfからIndex1.swfのプロパティやメソッドにアクセス出来なくなるわけではありません。こちらのアクセスはまた別の話。参照すれば親のメソッドを実行できます。

AさんのIndexでindex2.swfを読み込み表示する。

package{
	import flash.display.*;
	public class Index extends Sprite{
		public function Index(){
			trace( "Aさん" );
			var context:LoaderContext	= new LoaderContext( false, new ApplicationDomain( null ) );
			var loader:Loader	= new Loader();
			loader.load( new URLRequest( "Index2.swf" ), context );
			loader.contentLoaderInfo.addEventListener( Event.COMPLETE, 
				function onComplete(e:Event):void{
					addChild( loader );
				}
			);
		}
 
		public function onTest():void{
			trace( "Aさんのテスト" );
		}
	}
}

BさんのIndexで、AさんのIndexのメソッドを実行する。

package{
	import flash.display.*;
	public class Index extends Sprite{
		public function Index(){
			trace( "Bさん" );
			addEventListener( Event.ADDED_TO_STAGE,
				function( e:Event ):void{
					var parentIndex:Object = parent.parent as Object;
					if( parentIndex ) parentIndex.onTest();
				}
			);
		}
	}
}

逆に名前問題は解決していて子から親のクラスを使いたいってこともあると思います。
複数人での開発プロジェクトでは、セキュリティや受け渡しをしっかり話あっておかないと、合体させた時に思わぬトラブルに陥りそうですね。
Flashのセキュリティ関連は、バージョンが上がる度にややこしくなっているので、よくよく調べておこう。

参考:
ApplicationDomain クラスの使用
LoaderInfo
Flash Player セキュリティ

“ApplicationDomain” に コメントはありません

コメントをどうぞ