外部swfにリンケージされているクラスをnewしたい

ちょっとはまったのでメモ。

ミッション

メインswfから外部swf(アセット用swf)を読み込み、読み込んだアセットswにあるクラス(MyClass)をnewしたい。
ただし、MyClassはライブラリにあるMovieClipシンボルとリンケージされている。

図にするとこんな感じ
mission.gif
で、Main.asからこんな感じにnewしたい、と。

var myClass:MyClass = new MyClass();

その場合、何が問題なのか?

アセットswfにコンパイルされているMyClassが、ライブラリにあるシンボルとリンケージされている場合、
読み込み元に記述されているMyClassが競合する。

なぜか?

アセットにコンパイルされているMyClassと、読み込み元にコンパイルされているMyClassは同じ名前空間の同じクラス。
この場合、アセットswfを読み込んでも、読み込み元のMyClassはアセットのMyClassで上書きされない。
つまり、newできない。(リンケージしなければ可能)

思いついた3つの解決策

1・読み込み元にはクラスのimport記述をせず、型指定もしない。
ようするに読み込み元のswfにはMyClassをコンパイルしない。

var classRef : Class = getDefinitionByName("MyClass") as Class;
myClass = new classRef() as MovieClip;

2・読み込み元とは別のApplicationDomainにアセットを読み込む
この場合、main.swfにコンパイルされたMyClassと、読み込み元にコンパイルされているMyClassは、別のApplicationDomainになるので競合しない。

3・アセットswfではダミーのクラスをリンケージしておく
たとえば、dammyMyClassなどという識別子でリンケージし、クラスファイル(dammyMyClass.as)は作成しない。
(Flashはasset.swfコンパイル時に、自動的にダミーのクラスを作ってくれる。)
で、MyClassクラス内で、dammyMyClassをnewする

結論

1は、コンパイル時のエラーチェックが出来ない。
2は、アセットが関連するクラスはすべて、別のApplicationDomainにも存在する必要があるので、現実的じゃない。
いまのとこ、3がいいと思う。
ただし、この場合、MyClassはMovieClipを継承したクラスではなくMovieClipのラッパーとなる。
まぁ、MovieClipをどうしても継承したい局面が思い浮かばないので問題なし。

いろいろ書いたけど、個人的には
リンケージはいっさい使用しない!
これが最強。
AS2の頃からリンケージを使ってMovieClipをnewするのはすかんかった。

追記(2008/6/3):
と書いたものの、AS3のイベントモデルを堪能するにはMovieClipを継承しなければならない。最近は表示オブジェクトはコンポジットではなく継承するようにしています。なので、方法は3番だけど、MyClassはMovieClipを継承し、dammyMyClassをコンポジットするようにする。
これが今回のエントリについてのベストプラクティスだと思います。

カテゴリー: ActionScript3, AS3fromAS2 パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です