[ActionScript 3.0] クラス継承時のメンバの宣言と初期化の順序

2011 年 7 月 4 日 Tags: ,

package derivation {
	import flash.display.Sprite;
	
	public class SuperClass {
		
		protected var spr:Sprite = new Sprite;
		
		public function SuperClass() {
			
		}
		
	}

}

package derivation {

	public class SubClass extends SuperClass {
		
		private var alpha:Number = spr.alpha;
		
		public function SubClass() {
			
		}
		
	}

}

package  {
	import derivation.SubClass;
	import flash.display.Sprite;
	
	public class TestDerivation extends Sprite{
		
		public function TestDerivation() {
			new SubClass;
		}
		
	}

}

このコードを実行すると、コンパイルは通るがSubClassの側でsprがnullであると、実行時エラー出る。
しかし、SubClassを下記のように書き直すと問題ない。

package derivation {
	
	public class SubClass extends SuperClass{
		
		private var alpha:Number;
		
		public function SubClass() {
			alpha = spr.alpha;
		}
		
	}

}

オブジェクト指向(OOP)では、サブクラスが初期化される前にスーパークラスのすべてのメンバが初期化される。
だがActionScript 3.0では、なぜか下記のような順番になっているようだ。

スーパークラスのメンバの宣言

サブクラスのメンバの宣言と同時に初期化

スーパークラスのメンバの初期化(コンストラクタ)

サブクラスのメンバの初期化(コンストラクタ)

ソースコード上はメンバの宣言と同時に初期化していても、そのクラスがスーパークラスになる場合は自動で切り分けられ、宣言をしたあとにコンストラクタで初期化されているらしい。
そのため、サブクラスの側でスーパークラスのメンバを使ってサブクラスのメンバを宣言と同時に初期化しようとすると、まだスーパークラス側では初期化されていないため、エラーが出てしまう。
要注意。昔から言われているように、クラスのメンバはちゃんとコンストラクタの側にまとめて初期化のコードを書くほうがいいようだ。

ちなみに、Javaでは最初の例の書き方でも問題ない。