サイトトップ

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

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

静的プロパティ・メソッドの継承

ID: FN0701001 Product: Flash

Platform: All
Version: Flash 8 and above/ActionScript 2.0 and 3.0

ActionScriptでは、Mathクラスなどの静的なプロパティやメソッドを継承する場合、注意すべき点があります。FlashおよびActionScriptのバージョンによって、仕様や問題点も異なりますので、それらを分けて説明します。


1. Flash MX 2004/ActionScript 2.0の場合
Flash MX 2004のActionScript 2.0では、タイムラインからサブクラスのインスタンスを参照して、スーパークラスの静的メソッドにアクセスしようとすると問題が生じます。

たとえば、つぎのクラスMyMathは、Mathクラスを継承して、xy座標から度数の角度を返す静的メソッドgetAngle()を定義しています。メソッド内からは、Mathクラスのプロパティ(Math.PI)やメソッド(Math.atan2())を、Mathクラスの指定なしに(PIやatan2()のみで)参照することができます(スクリプト001)。

スクリプト001■座標から度数角を返す静的メソッドが定義されたクラスMyMath

// ActionScript 2.0クラス定義ファイル: MyMath.as
class MyMath extends Math {
  public static function getAngle(nX:Number, nY:Number):Number {
    var nRadian:Number = atan2(nY, nX);   // Math.atan2()を呼出し
    return nRadian/PI*180;   // Math.PIを参照
  }
}

もちろん、タイムラインからMyMath.getAngle()を呼出しても、正しく動作します。しかし、タイムラインからは、サブクラス MyMathを指定してスーパークラスMathのプロパティやメソッドは参照できません(スクリプト002)。

スクリプト002■タイムラインからクラスMyMathをテスト

// fla(swf)ファイル: テスト用
// タイムライン: _level0
// 第1フレームアクション
trace(MyMath.getAngle(1, 1));   // 出力: 45 ← 正常動作
trace([MyMath.PI, MyMath.atan2]);   // 出力: undefined,undefined ← 認識されていない

ただし、サブクラスを指定してスーパークラスの静的プロパティ・メソッドにアクセスできないのは、タイムラインからそれらを参照した場合です。処理をクラスに記述すれば、サブクラスからスーパークラスの静的プロパティ・メソッドを参照することは可能です(スクリプト003)。

スクリプト003■タイムラインからクラスMyMathをテスト

// ActionScript 2.0クラス定義ファイル: Test.as
class Test {
  public function Test() {
    // クラス内ならサブクラスから参照可能
    trace([MyMath.PI, MyMath.atan2]);   // 出力: 3.14159265358979,[type Function]
  }
}

// fla(swf)ファイル: テスト用
// タイムライン: _level0
// 第1フレームアクション
var obj:Test = new Test();

タイムラインに記述したスクリプト002で、サブクラスからスーパークラスの静的プロパティ・メソッドにアクセスできないのは、SWFに書出される際にスーパークラスへの参照が認識されないためのようです。スクリプトの冒頭にスーパークラスへのアクセスを1行加えると、スーパークラスの静的プロパティ・メソッドが参照できるようになります(スクリプト004)。

スクリプト004■タイムラインからクラスMyMathをテスト(修正)

// fla(swf)ファイル: テスト用
// タイムライン: _level0
// 第1フレームアクション
Math;   // スーパークラスにアクセス
trace(MyMath.getAngle(1, 1));   // 出力: 45
// スーパークラスの静的プロパティやメソッドが認識される
trace([MyMath.PI, MyMath.atan2]);   // 出力: 3.14159265358979,[type Function]


2. Flash 8/ActionScript 2.0の場合
Flash 8では、メインタイムラインから、サブクラスを指定してスーパークラスの静的プロパティやメソッドが参照できるようになったようです。前節のクラスMyMath(スクリプト001)を使って、タイムラインのフレームアクション(スクリプト002)を実行すると、つぎのように出力されます。

45
3.14159265358979,[type Function]

前述のとおり、スーパークラスMathへの参照はSWF、書出し時に正しく認識される必要があります。Flash 8でその参照が書出されたということは、Flash Playerのバージョンを7に設定してもSWFは正しく動作します。Flash Playerでなく、Flashアプリケーションの書出し処理の問題だからです。

ところが、同じ内容のスクリプトを、MovieClipシンボル内に記述すると、またスーパークラスの静的プロパティとメソッドが認識されなくなります。この場合も、スクリプトの冒頭でスーパークラスにアクセスしてあれば、正しく認識されるようになります(スクリプト005)。

スクリプト005■MovieClipからクラスMyMathをテスト

// fla(swf)ファイル: テスト用
// MovieClip: _level0.my_mc
// 第1フレームアクション
// つぎのコメントアウトを外すとスーパークラスの静的プロパティ・メソッドが参照できる
// Math;  
trace(MyMath.getAngle(1, 1));   // 出力: 45
trace([MyMath.PI, MyMath.atan2]);   // 出力: undefined,undefined

結論として、ActionScript 2.0では、タイムラインからサブクラスを指定してスーパークラスの静的プロパティやメソッドにアクセスすることは控えた方がよさそうです。その場合には、直接スーパークラスを指定して参照するのが確実です。


3. Flash 9/ActionScript 3.0の場合
「ActionScript 3.0 Language Reference」の「Class Math」の項を見ると、つぎのようにfinal属性が指定されています。

Class    public final class Math

final指定されたクラスは、継承することができません。ActionScript 3.0では、Mathクラスを継承すること自体がエラーになります。

さらに、ActionScript 3.0のstatic属性については、重大な注意点があります。「静的クラスメンバは、継承されません。静的クラスメンバを、JavaやC++のように、サブクラス名を使って参照することはできません」(「static属性キーワード」参照)[*1]

タイムラインからはもちろん、ActionScript 2.0と異なり他のクラス内からであっても、サブクラスを指定してスーパークラスの静的プロパティやメソッドは参照できません。ただし、サブクラス内からクラス指定なしにスーバークラスの静的プロパティ・メソッドにアクセスすることは可能です(スクリプト006)。

スクリプト006■MovieClipからクラスMyMathをテスト

// ActionScript 3.0クラス定義ファイル: MathBase.as
package {
  public class MathBase {
    public static const PI:Number = Math.PI;
    public static var atan2:Function = Math.atan2;
  }
}

// ActionScript 3.0クラス定義ファイル: MyMath30.as
package {
  public class MyMath30 extends MathBase { // MathBaseを継承
    public static function getAngle(nX:Number, nY:Number):Number {
      // スーパークラスの静的メソッドとプロパティを参照
      var nRadian:Number = atan2(nY, nX);
      return nRadian / PI * 180;
    }
  }
}

// ActionScript 3.0クラス定義ファイル: Test30.as
package {
  public class Test30 {
    public function Test30() {
      // サブクラス内からスーパークラスの静的メンバは参照可能
      trace(MyMath30.getAngle(1, 1)); // 出力: 45
      // サブクラスを指定してスーパークラスの静的メンバは参照できない
      trace([MyMath30.PI, MyMath30.atan2]); // コンパイルエラー
    }
  }
}

// fla(swf)ファイル: テスト用
// タイムライン: _level0
// 第1フレームアクション
var obj:Test30 = new Test30();

テスト用のクラスTest30内からであっても、サブクラスMyMath30を指定してスーパークラスMathBaseの静的プロパティ・メソッドにはアクセスできません。コンパイルエラーが発生します。しかし、サブクラスMyMath30の静的メソッドgetAngle()内からは、クラスの指定なしにスーパークラスMathBaseの静的プロパティPIやメソッドatan2()を参照することができます。

[*1] プロパティとメソッドをまとめて「メンバ」と呼びます。


作成者: 野中文雄
作成日: 2007年1月1日


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