サイトトップ

Director Flash 書籍 業務内容 プロフィール

Macromedia Flash非公式テクニカルノート

rootプロパティでメインタイムラインの関数にアクセスできない

ID: FN0707001 Product: Flash Platform: All Version: CS3/ActionScript 3.0

問題
メインタイムラインに記述されたつぎのフレームアクション(スクリプト001)は、問題なく動作します(図001)。

スクリプト001■メインタイムラインに関数を定義して呼出す

// メインタイムライン
// フレームアクション
function xTest():void {
   trace(this);
}
xTest();

図001■メインタイムラインの関数が呼出される
図001

ステージに表示されているタイムラインからは、メインタイムラインはDisplayObject.rootプロパティで参照することができます。もちろん、メインタイムラインからDisplayObject.rootプロパティにより、自身を参照することも可能です。そこで、上記スクリプト001に修正を加えて、メインタイムラインに定義している関数を、DisplayObject.rootを参照したうえで、呼出してみましょう。

スクリプト002■メインタイムラインの関数をroot参照つきで呼出す

// メインタイムライン
// フレームアクション
function xTest():void {
   trace(this);
}
// xTest();
root.xTest();

[ムービープレビュー]を行うと、デフォルトではつぎのようなエラーが表示されます(図001)[*1]

1061: 未定義である可能性のあるメソッドxTestを、静的型flash.display:DisplayObjectの参照を使用して呼び出しました。

図002■root参照つきでメインタイムラインの関数を呼出すとコンパイルエラー
図002

[*1] 「静的」な型というのは、データ型の指定を「コンパイル(SWF書出し)時」に評価していることを意味します。他方で、ActionScript 3.0では、「実行(ランタイム)時」の「動的」なエラーチェックが可能になりました。コンパイル時(静的)およびランタイム時(動的)の型チェックについては、オンラインヘルプ[ActionScript 3.0のプログラミング] > [ActionScript言語とシンタックス] > [データ型] > [型チェック]およびakihiro kamijo「AS3で動的言語のススメ」をご参照ください。


原因
[コンパイルエラー]の内容を、オンラインヘルプ[ActionScript 3.0コンポーネントリファレンスガイド] > [付録] > [コンパイラエラー]で確認してみましょう。すると、「定義されていないメソッドを呼び出しています」と説明されています。

「定義されていないメソッド」というのは、アクセスしているインスタンスにメソッド・関数が定義されていない。つまり[ActionScript 3.0コンポーネントリファレンスガイド]でそのクラスを調べてもそのメソッド・関数が掲載されていないということです。

ActionScript 3.0のデフォルトでは、このようにクラスに定義されていないプロパティやメソッドにアクセスすると、コンパイルエラーで警告してくれます。しかし、MovieClipインスタンスの場合、ユーザーはフレームアクションで自由に変数(プロパティ)や関数(メソッド)を定義することが可能です[*2]

このようにユーザーがプロパティやメソッドを追加できるクラスは、ダイナミック(dynamic)なクラスと呼ばれます。MovieClipクラスはダイナミックなクラスで、[ActionScript 3.0コンポーネントリファレンスガイド]の[MovieClipクラス]を見ると、dynamicというキーワードが記載されています(図003)[*3]

図003■MovieClipはダイナミック(dynamic)なクラス
図003

それでは、ダイナミックなクラスのインスタンスであるメインタイムラインに定義した関数が、なぜコンパイルエラーになるのでしょう? それは、rootがDisplayObjectクラスのプロパティだからです。[ActionScript 3.0コンポーネントリファレンスガイド]で[DisplayObjectクラス]を確認すると、下記のようにdynamicキーワードがありません。そのため、DisplayObjectクラスに定義されていないプロパティ(変数)やメソッド(関数)にアクセスしようとすると、コンパイルエラーが生じるのです。

クラス   public class DisplayObject

[*2] ActionScriptでは、変数とプロパティ、および関数とメソッドは、それぞれ同質のものとして扱われます。

[*3] 他にダイナミック(dynamic)なクラスとしては、Objectクラスがあります。


対処法
rootがDisplayObjectクラスのプロパティだとしても、今回このプロパティで参照しているのはMovieClipクラスのインスタンスであるメインタイムラインです。また、呼出している関数(function)も、確かにメインタイムラインのフレームアクションで定義してあります。このような場合、コンパイルエラーを避けるには、ふたつの方法があります。

[1] [strictモード]の解除
前出オンラインヘルプ[コンパイラエラー]の解説には、以下のような記載があります。そして、エラーコード1061の「未定義である可能性のあるメソッド」というコンパイルエラーは、まさに[strictモード]で発生します。

これらのエラーの一部は、strictモードでコードをコンパイルする場合にのみ検出されます。

したがって、[strictモード]を解除すれば、このコンパイルエラーは表示されません。そして、DisplayObject.rootプロパティの参照するメインタイムラインに、アクセス対象の関数が正しく定義されているかぎり、スクリプトは問題なく動作します。ただし、[strictモード]を解除した場合は、関数が定義されていなくてもエラーは発生しなくなります[*4]

[strictモード]を解除するには、[ファイル]メニューの[パブリッシュ設定]で[Flash]タブを選択し、ActionScript 3.0の[設定]ボタンをクリックして、[ActionScript 3.0設定]ダイアログボックスを開きます(図004)。[strictモード]のチェックを外せば、このオプションが解除されます[*5]

図004■[ActionScript 3.0設定]ダイアログボックスで[strictモード]を解除
図004

[2] キャスト
DisplayObject.rootは、DisplayObjectクラスのプロパティです。しかし、フレームアクションに記述したrootは、確実にMovieClipクラスのメインタイムラインを参照します。このような場合には、取得したDisplayObject.rootプロパティ値の型を、MovieClipクラスに変換することができます。

データ型を明示的に変換することは、一般に「キャスト」と呼ばれます。式の値を、あるクラスのデータ型にキャストするには、つぎのようなステートメントを記述します。

クラス(式);

それでは、前のスクリプト002を書替えて、rootプロパティをMovieClipでキャストしてみます(スクリプト003)。すると、[strictモード]でもコンパイルエラーは発生せず、メインタイムラインに定義した関数が正しく呼出されます(図005)。

スクリプト003■root参照をMovieClipでキャストしてメインタイムラインの関数を呼出す

// メインタイムライン
// フレームアクション
function xTest():void {
   trace(this);
}
// root.xTest();
MovieClip(root).xTest();

図005■MovieClipでキャストすると[strictモード]でも動作する
図005

[*4] MovieClipはダイナミックなクラスなので、[strictモード]を解除すると、定義されていないプロパティ・メソッドにアクセスしてもランタイムエラーは発生しません。たとえば、MovieClipインスタンスをDisplayObject型で指定したうえで、存在しないメソッドにアクセスしても、エラーはまったく生じません(図006)。

図006■MovieClipにないメソッドにアクセスしてもエラーにならない
図006

ダイナミックでない通常のクラス(たとえばSprite)のインスタンスであれば、[strictモード]を解除するとコード1061のコンパイルエラーは発生しないものの、ランタイムのエラーでメソッドが存在しないことを警告されます(図007)。

図007■Spriteにないメソッドにアクセスするとランタイムエラーになる
図007

[*5] Flash Professional 9 ActionScript 3.0 PreviewのFlashドキュメント(.fla)ファイル(あるいはFlash 8のファイルで[パブリッシュ設定]の[ActionScriptのバージョン]を[ActionScript 3.0]に変更した場合)は、[strictモード]が解除された設定になります。[strictモード]が解除された設定は、[standardモード]と呼ぶようです。


作成者: 野中文雄
更新日: 2007年7月8日 注釈[*5]を追加
作成日: 2007年7月5日


Copyright © 2001-2007 Fumio Nonaka.  All rights reserved.