クラス

クラスは、オブジェクトの抽象表現です。 クラスには、オブジェクトが保持できるデータの型およびオブジェクトが表すことができるビヘイビアーに関する情報が格納されます。 相互にやり取りする 2、3 個のオブジェクトのみを含む小さなスクリプトを記述する場合には、このような抽象化の利点はわかりにくいかもしれません。しかし、プログラムのスコープが拡大するほど、管理しなければならないオブジェクトの数が増加します。そのような場合、クラスを使用することで、オブジェクトの作成方法と、オブジェクトの相互のやり取りの方法を制御しやすくなります。

ActionScript 1.0 では、Function オブジェクトを使用してクラスに似たコンストラクトを作成できました。 ActionScript 2.0 では、classextends などのキーワードによるクラスのサポートが正式に追加されました。ActionScript 3.0 では、ActionScript 2.0 で導入されたキーワードを引き続きサポートするだけでなく、新しい機能も追加されています。例えば、ActionScript 3.0 では、protected 属性と internal 属性により、アクセス制御が強化されています。また、final キーワードおよび override キーワードによる継承も、より的確に制御できるようになりました。

Java、C++、C# などのプログラミング言語でクラスを作成した経験があれば、ActionScript でも同じように作成できます。ActionScript には、classextendspublic など、これらのプログラミング言語と共通するキーワード名と属性名が多数存在します。

注意: Adobe ActionScript マニュアルでは、「プロパティ」という用語は、オブジェクトまたはクラスのあらゆるメンバー(変数、定数、メソッドなど)を示します。また、「クラス」と「静的」という用語はよく同じ意味で使用されますが、このマニュアルではこの 2 つの用語を区別します。例えば、「クラスプロパティ」という語句は、静的メンバーだけではなく、クラスのすべてのメンバーを指します。

クラス定義

ActionScript 3.0 のクラス定義には、ActionScript 2.0 のクラス定義に使用したシンタックスとほぼ同じシンタックスを使用します。クラス定義の正しいシンタックスは、class キーワードの後にクラス名が必要です。クラス名の後には、中括弧({})で囲まれたクラス本体が続きます。例えば、次のコードは、visible という名前の変数を 1 つ含む Shape という名前のクラスを作成します。

public class Shape 
{ 
    var visible:Boolean = true; 
}

シンタックスが大きく変更された点の 1 つに、パッケージ内のクラス定義があります。 ActionScript 2.0 では、クラスがパッケージ内部にある場合は、クラス宣言にパッケージ名を含める必要があります。 ActionScript 3.0 では package ステートメントが導入されていますが、パッケージ名は、クラス宣言ではなくパッケージ宣言に含める必要があります。例えば、次のクラス宣言は、flash.display パッケージに含まれる BitmapData クラスを、ActionScript 2.0 および ActionScript 3.0 で定義する方法を示します。

// ActionScript 2.0 
class flash.display.BitmapData {} 
 
// ActionScript 3.0 
package flash.display 
{ 
    public class BitmapData {} 
}

クラス属性

ActionScript 3.0 では、次の 4 つの属性のいずれかを使用して、クラス定義を変更できます。

属性

定義

dynamic

実行時にインスタンスにプロパティを追加できます。

final

別のクラスによって拡張することはできません。

internal(デフォルト)

現在のパッケージ内の参照に対して表示されます。

public

すべての場所にある参照に対して表示されます。

internal を除くこれらの属性では、属性を明示的に含めて関連付けられたビヘイビアーを取得します。例えば、クラスを定義するときに dynamic 属性を含めなかった場合、実行時にクラスインスタンスにプロパティを追加することはできません。次のコードで示すように、クラス定義の開始部分に属性を配置することで、明示的に属性を割り当てます。

dynamic class Shape {}

このリストには、abstract という名前の属性は含まれていません。これは抽象クラスが ActionScript 3.0 でサポートされていないためです。また、このリストには、private および protected という名前の属性も含まれていません。これらの属性は、クラス定義内でのみ意味を持ち、クラス自体には適用できません。 パッケージの外部でクラスをパブリックに表示しない場合は、パッケージ内にクラスを配置し、internal 属性でクラスを宣言します。または、internal 属性と public 属性の両方を省略することもできます。この場合は、コンパイラーが自動的に internal 属性を追加します。定義されたソースファイル内でのみ参照されるように、クラスを定義することもできます。それには、パッケージ定義の右中括弧の下、ソースファイルの最後にクラスを挿入します。

クラス本体

クラス本体は、中括弧で囲みます。クラス本体は、クラスの変数、定数、メソッドを定義します。次の例は、ActionScript 3.0 の Accessibility クラスの宣言を示します。

public final class Accessibility 
{ 
    public static function get active():Boolean; 
    public static function updateProperties():void; 
}

クラス本体内で名前空間を定義することもできます。 次の例は、クラス本体内で名前空間を定義し、そのクラスのメソッドの属性として使用する方法を示します。

public class SampleClass 
{ 
    public namespace sampleNamespace; 
    sampleNamespace function doSomething():void; 
}

ActionScript 3.0 では、クラス本体内に、定義だけでなくステートメントを含めることもできます。 クラス本体内にあるが、メソッド定義の外にあるステートメントは、1 度だけ実行されます。この実行は、クラス定義が最初に検出され、関連付けられたクラスオブジェクトが作成されるときに発生します。次の例には、外部関数である hello() と、クラスが定義されたときに確認メッセージを出力する trace ステートメントの呼び出しが含まれています。

function hello():String 
{ 
    trace("hola"); 
} 
class SampleClass 
{ 
    hello(); 
    trace("class created"); 
} 
// output when class is created 
hola 
class created

ActionScript 3.0 では、同じクラス本体内で同じ名前を持つ静的プロパティとインスタンスプロパティを定義することができます。例えば、次のコードは、message という名前の静的変数と同じ名前のインスタンス変数を宣言します。

class StaticTest 
{ 
    static var message:String = "static variable"; 
    var message:String = "instance variable"; 
} 
// In your script 
var myST:StaticTest = new StaticTest(); 
trace(StaticTest.message); // output: static variable 
trace(myST.message); // output: instance variable

クラスプロパティの属性

ActionScript オブジェクトモデルの説明では、プロパティという用語は、変数、定数、メソッドなど、クラスのメンバーになり得るものすべてを意味します。しかし、Adobe Flash Professional CS5 用 ActionScript 3.0 リファレンスガイドでは、この用語はより狭い意味で使用されます。このリファレンスでは、プロパティは、変数であるクラスメンバー、または getter メソッドか setter メソッドで定義されたクラスメンバーを指します。ActionScript 3.0 には、クラスのプロパティと共に使用できる一連の属性があります。 次の表は、この属性の一覧です。

属性

定義

internal(デフォルト)

同じパッケージ内の参照に対して表示されます。

private

同じクラス内の参照に対して表示されます。

protected

同じクラスおよび派生クラス内の参照に対して表示されます。

public

すべての場所にある参照に対して表示されます。

static

プロパティが、クラスのインスタンスではなくクラスに属することを指定します。

UserDefinedNamespace

ユーザーが定義するカスタム名前空間の名前です。

アクセス制御名前空間の属性

ActionScript 3.0 には、クラス内で定義されたプロパティへのアクセスを制御する 4 つの特別な属性、publicprivateprotected、および internal があります。

public 属性は、スクリプト内の任意の場所でプロパティを表示します。例えば、パッケージ外部のコードでメソッドを使用するには、public 属性でメソッドを宣言する必要があります。これは、宣言されたキーワードが varconstfunction のいずれであるかにかかわらず、あらゆるプロパティに当てはまります。

private 属性は、プロパティが定義されたクラス内の呼び出し元に対してのみプロパティを表示します。このビヘイビアーは、サブクラスがスーパークラスのプライベートプロパティにアクセスできる ActionScript 2.0 の private 属性とは異なります。ランタイムアクセスに関しても、ビヘイビアーが大きく変更されています。 ActionScript 2.0 では、private キーワードによりアクセスが禁止されるのはコンパイル時のみで、実行時にはアクセスが禁止されません。ActionScript 3.0 では、これは当てはまりません。 private とマークされたプロパティは、コンパイル時も実行時も使用することができません。

例えば、次のコードは、プライベート変数を 1 つ持つ PrivateExample という単純なクラスを作成し、クラス外部からこのプライベート変数にアクセスしようとします。

class PrivateExample 
{ 
    private var privVar:String = "private variable"; 
} 
 
var myExample:PrivateExample = new PrivateExample(); 
trace(myExample.privVar);// compile-time error in strict mode 
trace(myExample["privVar"]); // ActionScript 2.0 allows access, but in ActionScript 3.0, this is a run-time error. 

ActionScript 3.0 では、ドット演算子(myExample.privVar)を使用してプライベートプロパティにアクセスしようとすると、strict モードを使用している場合にコンパイル時エラーになります。それ以外の場合は、プロパティアクセス演算子(myExample["privVar"])を使用するときと同様に、エラーは実行時に報告されます。

次の表に、sealed(dynamic ではない)クラスに属するプライベートプロパティにアクセスしようとした結果の概要を示します。

 

strict モード

standard モード

ドット演算子(.

コンパイル時エラー

ランタイムエラー

角括弧演算子([]

ランタイムエラー

ランタイムエラー

dynamic 属性で宣言されたクラスでは、プライベート変数にアクセスしようとしても、ランタイムエラーにはなりません。ただし、変数が参照不可になるため、undefined という値が返されます。しかし、strict モードでドット演算子を使用すると、コンパイル時エラーが発生します。 次の例は、PrivateExample クラスがダイナミッククラスとして宣言されている点を除き、前の例と同じです。

dynamic class PrivateExample 
{ 
    private var privVar:String = "private variable"; 
} 
 
var myExample:PrivateExample = new PrivateExample(); 
trace(myExample.privVar);// compile-time error in strict mode 
trace(myExample["privVar"]); // output: undefined

通常、ダイナミッククラスは、クラス外部のコードがプライベートプロパティにアクセスしようとすると、エラーを生成するのではなく、戻り値として undefined を返します。次の表は、ドット演算子を使用して strict モードでプライベートプロパティにアクセスしようとしたときにのみエラーが生成されることを示します。

 

strict モード

standard モード

ドット演算子(.

コンパイル時エラー

undefined

角括弧演算子([]

undefined

undefined

ActionScript 3.0 で新しく導入された protected 属性は、クラス内またはサブクラス内の呼び出し元に対してプロパティを表示します。つまり、protected プロパティは、そのクラス内または継承階層内でそのクラスの下の任意の場所にあるクラスで使用することができます。 これは、サブクラスが同じパッケージ内にあるか別のパッケージ内にあるかに関係なく、同じです。

ActionScript 2.0 に詳しいユーザーにとっては、この機能は ActionScript 2.0 の private 属性とほぼ同じです。また、ActionScript 3.0 の protected 属性は Java の protected 属性とほぼ同じですが、Java のこの属性は同じパッケージ内の呼び出し元へのアクセスも許可するという点で異なります。ただし、Java では、この属性は同じパッケージ内の呼び出し元へのアクセスも許可するという点で異なります。protected 属性は、サブクラスで必要なメソッドまたは変数を継承チェーン外部のコードに対して非表示にするときに便利です。

ActionScript 3.0 で新しく導入された internal 属性は、パッケージ内にある呼び出し元に対してプロパティを表示します。これはパッケージ内のコードのデフォルト属性であり、次のいずれの属性も持たないあらゆるプロパティに適用されます。

  • public

  • private

  • protected

  • ユーザー定義の名前空間

internal 属性は、Java のデフォルトのアクセス制御に似ています。ただし、Java ではこのレベルのアクセスに明示的な名前はなく、他のアクセス修飾子が省略された場合にのみ、このデフォルトのアクセス制御が使用されます。internal 属性は ActionScript 3.0 で使用可能で、パッケージ内の呼び出し元に対してのみプロパティを表示する意図を明示的に表すオプションがあります。

static 属性

static 属性は、varconst、または function キーワードで宣言されたプロパティと共に使用でき、クラスのインスタンスではなくクラスにプロパティを関連付けることができます。クラス外にあるコードは、インスタンス名ではなくクラス名を使用して静的プロパティを呼び出す必要があります。

静的プロパティはサブクラスに継承されませんが、サブクラスのスコープチェーンの一部です。つまり、サブクラスの本体内では、静的変数またはメソッドは、定義されたクラスを参照しなくても使用できます。

ユーザー定義の名前空間属性

事前に定義されているアクセス制御属性の代わりに、属性として使用するカスタム名前空間を作成できます。 1 つの定義に使用できる名前空間属性は 1 つだけです。また、名前空間属性をアクセス制御属性(publicprivateprotectedinternal)と組み合わせて使用することはできません。

変数

変数は、var キーワードか const キーワードで宣言できます。var キーワードで宣言した変数は、スクリプトの実行中に複数回その値を変更できます。const キーワードで宣言した変数は定数と呼ばれ、1 回だけ値を割り当てることができます。初期化された定数に新しい値を割り当てようとすると、エラーが発生します。

静的変数

静的変数は、static キーワードと、var または const ステートメントのいずれかの組み合わせを使用して宣言します。クラスのインスタンスではなく、クラスに関連付けられた静的変数は、オブジェクトのクラス全体に適用される情報の格納および共有に役立ちます。 例えば、静的変数は、クラスがインスタンス化された回数を記録する場合や可能なクラスインスタンスの最大数を格納しておく場合に適しています。

次の例では、クラスのインスタンス化の回数を追跡する totalCount 変数およびインスタンス化の最大回数を格納する MAX_NUM 定数を作成します。totalCountMAX_NUM 変数には、特定のインスタンスではなくクラス全体に適用される値が含まれているので、この 2 つの変数は静的です。

class StaticVars 
{ 
    public static var totalCount:int = 0; 
    public static const MAX_NUM:uint = 16; 
}

StaticVars クラスとそのサブクラスの外部にあるコードは、StaticVars クラス自体を通じた場合にのみ、totalCount プロパティと MAX_NUM プロパティを参照できます。例えば、次のコードは正常に動作します。

trace(StaticVars.totalCount); // output: 0 
trace(StaticVars.MAX_NUM); // output: 16

クラスのインスタンスから静的変数にアクセスできないため、次のコードはエラーを返します。

var myStaticVars:StaticVars = new StaticVars(); 
trace(myStaticVars.totalCount); // error 
trace(myStaticVars.MAX_NUM); // error

static および const の 2 つのキーワードで宣言された変数は、StaticVars クラスが MAX_NUM に対する場合と同様に、定数の宣言時に初期化する必要があります。コンストラクターまたはインスタンスメソッド内の MAX_NUM に値を割り当てることはできません。次のコードは静的定数を初期化する有効な方法ではないため、エラーが生成されます。

// !! Error to initialize static constant this way 
class StaticVars2 
{ 
    public static const UNIQUESORT:uint; 
    function initializeStatic():void 
    { 
        UNIQUESORT = 16; 
    } 
}

インスタンス変数

インスタンス変数には、var および const キーワードを使用し、static キーワードを使用せずに宣言されたプロパティが含まれます。クラス全体ではなくクラスインスタンスに関連付けられたインスタンス変数は、インスタンス固有の値の格納に便利です。 例えば、Array クラスには、この Array クラスの特定のインスタンスが保持する配列エレメントの数を格納する length という名前のインスタンスプロパティがあります。

インスタンス変数は、var または const として宣言されたかどうかにかかわらず、サブクラスではオーバーライドできません。ただし、getter および setter メソッドをオーバーライドすることにより、変数をオーバーライドするのに似た機能を実現できます。

メソッド

メソッドは、クラス定義に含まれる関数です。 クラスのインスタンスが作成されると、メソッドはそのインスタンスにバインドされます。 メソッドは、クラス外で宣言された関数とは異なり、その関連付けられているインスタンスと別個に使用することはできません。

メソッドは、function キーワードを使用して定義します。あらゆるクラスプロパティと同様に、どのクラスプロパティ属性も、private、protected、public、internal、static、などのメソッドや、カスタム名前空間に適用できます。次の function ステートメントを使用できます。

public function sampleFunction():String {}

または、関数式を割り当てる変数を次のように使用することもできます。

public var sampleFunction:Function = function () {}

多くの場合、関数式ではなく function ステートメントを使用するのは、次のような理由のためです。

  • function ステートメントは、関数式より簡潔で読みやすくなります。

  • function ステートメントでは、override および final キーワードを使用できます。

  • function ステートメントでは、識別子(関数の名前)とメソッド本体内のコードがより強力に結合されます。変数の値は代入ステートメントで変更できるので、変数とその関数式の結合をいつでも切り離すことができます。var ではなく const で変数を宣言するとこの問題を回避できますが、コードが読みにくくなり、override キーワードと final キーワードが使用できなくなるので、最適な方法とは言えません。

関数式を使用する必要があるのは、関数をプロトタイプオブジェクトに関連付ける場合などです。

コンストラクターメソッド

単にコンストラクターと呼ばれることもあるコンストラクターメソッドは、定義されたクラスと同じ名前を共有する関数です。コンストラクターメソッドに含まれるコードは、クラスのインスタンスが new キーワードで作成されるときに実行されます。例えば、次のコードは、status という名前のプロパティを 1 つ含む単純なクラス Example を定義します。status 変数の初期値は、コンストラクター関数内で設定します。

class Example 
{ 
    public var status:String; 
    public function Example() 
    { 
        status = "initialized"; 
    } 
} 
 
var myExample:Example = new Example(); 
trace(myExample.status); // output: initialized

コンストラクターメソッドにはパブリックだけを指定できますが、public 属性を使用するかどうかは任意です。コンストラクターに、privateprotectedinternal やその他のアクセス制御指定子を使用することはできません。また、ユーザー定義の名前空間をコンストラクターメソッドで使用することもできません。

コンストラクターは、super() ステートメントを使用して直接のスーパークラスのコンストラクターを明示的に呼び出すことができます。スーパークラスのコンストラクターを明示的に呼び出さない場合は、コンパイラーによってコンストラクター本体の最初のステートメントの前に呼び出しが自動的に挿入されます。 スーパークラスへの参照として super 接頭辞を使用し、スーパークラスのメソッドを呼び出すこともできます。同じコンストラクター本体で super()super を使用する場合は、必ず最初に super() を呼び出します。そうしないと、super 参照が意図したとおりに動作しません。super() コンストラクターも、throw または return ステートメントの前に呼び出す必要があります。

次に、super() コンストラクターを呼び出す前に super 参照を使用しようとした場合の例を示します。新しいクラス ExampleEx は Example クラスを拡張します。 ExampleEx コンストラクターは、super() を呼び出す前に、スーパークラスで定義された status 変数にアクセスしようとします。ExampleEx コンストラクター内の trace() ステートメントは、値 null を生成します。これは、super() コンストラクターが実行されるまで status 変数を使用できないからです。

class ExampleEx extends Example 
{ 
    public function ExampleEx() 
    { 
        trace(super.status); 
        super(); 
    } 
} 
 
var mySample:ExampleEx = new ExampleEx(); // output: null

コンストラクター内で return ステートメントを使用することはできますが、値を返すことはできません。つまり、return ステートメントに式または値を関連付けることはできません。したがって、コンストラクターメソッドは値を返すことができず、戻り値の型を指定できません。

クラスでコンストラクターメソッドを定義しなかった場合、コンパイラーが自動的に空のコンストラクターを作成します。クラスが別のクラスを拡張する場合、コンパイラーには、そのコンパイラーが生成するコンストラクター内の super() 呼び出しが含まれます。

静的メソッド

静的メソッドは、クラスメソッドとも呼ばれ、static キーワードで宣言されたメソッドです。静的メソッドは、クラスのインスタンスではなくクラスに関連付けられ、個々のインスタンスの状態以外のものに影響を与える機能のカプセル化に役立ちます。 静的メソッドはクラス全体に関連付けられるため、クラスのインスタンスではなくクラスからのみアクセスできます。

静的メソッドは、クラスインスタンスの状態に影響を与えるだけではない機能のカプセル化に役立ちます。 つまり、メソッドにクラスインスタンスの値に直接影響しない機能がある場合、そのメソッドは静的です。 例えば、Date クラスには、ストリングを取得して数値に変換する parse() という静的メソッドがあります。このメソッドは、クラスの個々のインスタンスに影響を与えないため静的です。 parse() メソッドは、日付値を表すストリングを取得し、そのストリングを解析して、Date オブジェクトの内部表現と互換性がある形式で数値を返します。このメソッドは、Date クラスのインスタンスに適用しても意味がないため、インスタンスメソッドではありません。

静的な parse() メソッドと、getMonth() などの Date クラスのインスタンスメソッドを比較してみます。getMonth() メソッドは、Date インスタンスの特定のコンポーネント月を取得することで、インスタンスの値に対して直接実行されるため、インスタンスメソッドです。

静的メソッドは個々のインスタンスにバインドされていないので、静的メソッドの本体内で this または super キーワードを使用できません。this 参照と super 参照は、インスタンスメソッドのコンテキスト内でのみ有効です。

他のクラスベースのプログラミング言語とは異なり、ActionScript 3.0 では静的メソッドは継承されません。

インスタンスメソッド

インスタンスメソッドは、static キーワードを使用せずに宣言されたメソッドです。インスタンスメソッドは、クラス全体ではなくクラスのインスタンスに関連付けられ、クラスの個々のインスタンスに影響を与える機能の実装に役立ちます。 例えば、Array クラスには、Array インスタンスに直接実行される sort() という名前のインスタンスメソッドが含まれています。

インスタンスメソッドの本体内では、静的変数およびインスタンス変数はスコープ内にあります。つまり、同じクラス内で定義された変数は、単純な識別子を使用して参照できます。 例えば、次の CustomArray クラスは Array クラスを拡張します。 CustomArray クラスは、クラスインスタンスの総数を追跡する静的変数 arrayCountTotal、インスタンスが作成された順序を追跡するインスタンス変数 arrayNumber、およびこれらの変数の値を返すインスタンスメソッド getPosition() を定義します。

public class CustomArray extends Array 
{ 
    public static var arrayCountTotal:int = 0; 
    public var arrayNumber:int; 
 
    public function CustomArray() 
    { 
        arrayNumber = ++arrayCountTotal; 
    } 
     
    public function getArrayPosition():String 
    { 
         return ("Array " + arrayNumber + " of " + arrayCountTotal); 
    } 
}

クラス外部にあるコードは、CustomArray.arrayCountTotal を使用して、クラスオブジェクトから arrayCountTotal 静的変数にアクセスする必要がありますが、getPosition() メソッドの本体内にあるコードは、arrayCountTotal 静的変数を直接参照できます。これは、スーパークラスの静的変数でも同じです。 ActionScript 3.0 では静的プロパティは継承されませんが、スーパークラスの静的プロパティはスコープ内です。 例えば、Array クラスにはいくつかの静的変数があり、そのうちの 1 つは DESCENDING という定数です。Array サブクラス内にあるコードは、単純な識別子を使用して静的定数 DESCENDING にアクセスできます。

public class CustomArray extends Array 
{ 
    public function testStatic():void 
    { 
        trace(DESCENDING); // output: 2 
    } 
}

インスタンスメソッドの本体内の this 参照の値は、メソッドが関連付けられているインスタンスへの参照です。次のコードは、this 参照がメソッドを含むインスタンスを参照していることを示します。

class ThisTest 
{ 
    function thisValue():ThisTest 
    { 
        return this; 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
trace(myTest.thisValue() == myTest); // output: true

インスタンスメソッドの継承は、override キーワードと final キーワードを使用して制御できます。override 属性を使用すると、継承したメソッドを再定義できます。また、final 属性を使用すると、そのメソッドをサブクラスでオーバーライドすることを禁止できます。

get および set アクセッサーメソッド

getter および setter とも呼ばれる get および set アクセッサー関数を使用すると、作成したクラスの使いやすいプログラミングインターフェイスを提供すると同時に、情報の非表示およびカプセル化というプログラミング原則に従うことができます。get および set 関数を使用して、クラスプロパティをクラスに対してプライベートに保持できますが、クラスのユーザーは、クラスメソッドを呼び出すのではなくクラス変数にアクセスしている場合と同じように、これらのプロパティにアクセスできます。

この方法の利点は、getPropertyName()setPropertyName() など、従来の冗長な名前のアクセッサー関数を使用する必要がないことです。また、getter および setter には、読み取りおよび書き込みアクセスを可能にする各プロパティに対して 2 つの公開関数を持つ必要がないという利点もあります。

次の例の GetSet クラスには、privateProperty という名前のプライベート変数へのアクセスを提供する publicAccess() という名前の get および set アクセッサー関数が含まれています。

class GetSet 
{ 
    private var privateProperty:String; 
     
    public function get publicAccess():String 
    { 
        return privateProperty; 
    } 
     
    public function set publicAccess(setValue:String):void 
    { 
        privateProperty = setValue; 
    } 
}

privateProperty プロパティに直接アクセスしようとすると、次のエラーが発生します。

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.privateProperty); // error occurs

代わりに、GetSet クラスを使用する場合は、publicAccess というプロパティのように見えて、実際には privateProperty という名前のプライベートプロパティに対して動作する get および set アクセッサー関数のペアを使用します。次の例では、GetSet クラスをインスタンス化し、publicAccess という名前のパブリックアクセッサーを使用して privateProperty の値を設定します。

var myGetSet:GetSet = new GetSet(); 
trace(myGetSet.publicAccess); // output: null 
myGetSet.publicAccess = "hello"; 
trace(myGetSet.publicAccess); // output: hello

getter および setter 関数でも、スーパークラスから継承されるプロパティをオーバーライドできますが、通常のクラスメンバー変数を使用したときにはオーバーライドできません。 var キーワードで宣言されたクラスメンバー変数は、サブクラスではオーバーライドできません。一方、getter および setter 関数を使用して作成されたプロパティにはこの制限はありません。 スーパークラスから継承した getter 関数と setter 関数に override 属性を使用できます。

バインドメソッド

バインドメソッドは、メソッドクロージャとも呼ばれ、単にインスタンスから抽出されるメソッドです。バインドメソッドの例には、関数にパラメーターとして渡され、関数から値として返されるメソッドがあります。 ActionScript 3.0 で新しく導入されたバインドメソッドは、インスタンスから抽出されたときでもレキシカル環境が保持されるメソッドクロージャに似ています。 バインドメソッドとメソッドクロージャの主な違いは、バインドメソッドの this 参照は、バインドメソッドを実装するインスタンスにリンクされたまま、つまりバインドされたままであるという点です。つまり、バインドメソッドの this 参照が、常にこのメソッドを実装する元のオブジェクトを指していることを意味します。関数クロージャの場合、this 参照は汎用です。つまり、この関数が呼び出された時点で関連付けられているオブジェクトが何であっても、そのオブジェクトを参照します。

this キーワードを使用する場合は、バインドメソッドを理解していることが重要です。this キーワードを使用すれば、メソッドの親オブジェクトを参照できます。ほとんどの ActionScript プログラマーは、this キーワードが常にメソッドの定義を含むオブジェクトまたはクラスを表すと考えますが、メソッドのバインディングがないと必ずしもそうなりません。 旧バージョンの ActionScript では、例えば、this 参照はメソッドを実装するインスタンスを常に参照するわけではありませんでした。ActionScript 2.0 でインスタンスからメソッドを抽出すると、this 参照が元のインスタンスにバインドされないだけでなく、インスタンスのクラスのメンバー変数もメソッドも使用できません。ActionScript 3.0 では、メソッドをパラメーターとして渡すとバインドメソッドが自動的に作成されるため、これは問題にはなりません。 バインドメソッドにより、this キーワードは常に、メソッドが定義されたオブジェクトまたはクラスを参照します。

次のコードは、ThisTest というクラスを定義します。このクラスには、バインドメソッドを定義するメソッド foo()、およびバインドメソッドを返すメソッド bar() が含まれます。クラス外部にあるコードは、ThisTest クラスのインスタンスを作成し、bar() メソッドを呼び出して、myFunc という変数に戻り値を格納します。

class ThisTest 
{ 
    private var num:Number = 3; 
    function foo():void // bound method defined 
    { 
        trace("foo's this: " + this); 
        trace("num: " + num); 
    } 
    function bar():Function 
    { 
        return foo; // bound method returned 
    } 
} 
 
var myTest:ThisTest = new ThisTest(); 
var myFunc:Function = myTest.bar(); 
trace(this); // output: [object global] 
myFunc(); 
/* output:  
foo's this: [object ThisTest] 
output: num: 3 */

コードの最後の 2 行は、バインドメソッド foo()this 参照が、その直前の行の this 参照がグローバルオブジェクトを指していても、依然として ThisTest クラスのインスタンスを指すことを示しています。さらに、myFunc 変数に格納されているバインドメソッドは、引き続き ThisTest クラスのメンバー変数にアクセスできます。この同じコードを ActionScript 2.0 で実行すると、this 参照が一致し、num 変数は undefined になります。

addEventListener() メソッドでは関数またはメソッドをパラメーターとして渡す必要があるため、バインドメソッドの追加が最もわかりやすいのはイベントハンドラーを使用する場合です。

クラスによる列挙

列挙は、値の小さなセットをカプセル化するために作成するカスタムデータ型です。 ActionScript 3.0 は、C++ の enum キーワードや Java の Enumeration インターフェイスとは異なり、特定の列挙機能をサポートしません。ただし、クラスと静的定数を使用して列挙を作成できます。 例えば、次のコードに示すように、ActionScript 3.0 の PrintJob クラスは PrintJobOrientation という列挙を使用して、"landscape" および "portrait" という値を格納します。

public final class PrintJobOrientation 
{ 
    public static const LANDSCAPE:String = "landscape"; 
    public static const PORTRAIT:String = "portrait"; 
}

慣例では、列挙クラスはクラスを拡張する必要がないので、final 属性で宣言されます。このクラスは静的メンバーのみで構成されます。つまり、クラスのインスタンスを作成しません。代わりに、次の抜粋されたコードに示すように、クラスオブジェクトを通じて直接列挙値にアクセスします。

var pj:PrintJob = new PrintJob(); 
if(pj.start()) 
{ 
    if (pj.orientation == PrintJobOrientation.PORTRAIT) 
    { 
        ... 
    } 
    ... 
}

ActionScript 3.0 内のすべての列挙クラスには、String、int、または uint のいずれかの型の変数のみが含まれます。リテラルのストリング値または数値ではなく列挙を使用する利点は、表記ミスを見つけやすいことです。 列挙の名前を間違って入力した場合、ActionScript コンパイラーはエラーを生成します。 リテラル値を使用した場合、単語を間違って入力するか数値を間違って使用してもコンパイラーに認識されません。 前の例では、次のコードの抜粋に示すように、列挙定数の名前が間違っている場合にコンパイラーはエラーを生成します。

    if (pj.orientation == PrintJobOrientation.PORTRAI) // compiler error

しかし、次のようにリテラルストリング値にスペルミスがある場合、コンパイラーはエラーを生成しません。

    if (pj.orientation == "portrai") // no compiler error

列挙を作成するもう 1 つの方法でも、列挙の静的プロパティで別のクラスを作成することが必要になります。 ただし、この方法は、静的プロパティにストリング値または整数値ではなくクラスのインスタンスが含まれる点で異なります。 例えば、次のコードは、曜日に対する列挙クラスを作成します。

public final class Day 
{ 
    public static const MONDAY:Day = new Day(); 
    public static const TUESDAY:Day = new Day(); 
    public static const WEDNESDAY:Day = new Day(); 
    public static const THURSDAY:Day = new Day(); 
    public static const FRIDAY:Day = new Day(); 
    public static const SATURDAY:Day = new Day(); 
    public static const SUNDAY:Day = new Day(); 
}

ActionScript 3.0 ではこの方法は使用されていませんが、この方法により型チェックの向上を希望する多くの開発者によって採用されています。例えば、列挙値を返すメソッドは、その戻り値を列挙データ型に制限することができます。 次のコードは、曜日を返す関数だけでなく、列挙型を型注釈として使用する関数呼び出しも示します。

function getDay():Day 
{ 
    var date:Date = new Date(); 
    var retDay:Day; 
    switch (date.day) 
    { 
        case 0: 
            retDay = Day.MONDAY; 
            break; 
        case 1: 
            retDay = Day.TUESDAY; 
            break; 
        case 2: 
            retDay = Day.WEDNESDAY; 
            break; 
        case 3: 
            retDay = Day.THURSDAY; 
            break; 
        case 4: 
            retDay = Day.FRIDAY; 
            break; 
        case 5: 
            retDay = Day.SATURDAY; 
            break; 
        case 6: 
            retDay = Day.SUNDAY; 
            break; 
    } 
    return retDay; 
} 
 
var dayOfWeek:Day = getDay();

Day クラスを拡張することにより、整数を各曜日に関連付け、曜日のストリング表現を返す toString() メソッドを提供することもできます。

埋め込みアセットクラス

ActionScript 3.0 では、埋め込みアセットを表現するために、埋め込みアセットクラスと呼ばれる特別なクラスを使用します。埋め込みアセットは、コンパイル時に SWF ファイルに含まれるサウンド、イメージ、フォントなどのアセットです。アセットは、動的にロードするのではなく埋め込むことで実行時に確実に利用できるようになりますが、この方法には SWF ファイルのサイズが大きくなるという短所があります。

Flash Professional での埋め込みアセットクラスの使用

アセットを埋め込むには、まずアセットを FLA ファイルのライブラリに保存します。次に、アセットのリンケージプロパティを使用して、アセットの埋め込みアセットクラスの名前を指定します。 その名前のクラスがクラスパスに見つからない場合、クラスは自動的に生成されます。 これにより、埋め込みアセットクラスのインスタンスを作成し、そのクラスによって定義または継承された任意のプロパティとメソッドを使用できるようになります。 例えば、次のコードを使用して、PianoMusic という名前の埋め込みアセットクラスにリンクされた埋め込みサウンドを再生できます。

var piano:PianoMusic = new PianoMusic(); 
var sndChannel:SoundChannel = piano.play();

または、次で説明するとおり、[Embed] メタデータタグを使用して Flash Professional プロジェクトにアセットを埋め込むこともできます。コード内に [Embed] メタデータタグがあると、プロジェクトのコンパイル時に、Flash Professional コンパイラーではなく Flex コンパイラーが使用されます。

Flex コンパイラーを使用した埋め込みアセットクラスの使用

Flex コンパイラーを使用してコードをコンパイルする場合、アセットを ActionScript コードに埋め込むには、[Embed] メタデータタグを使用します。メインソースフォルダーか、プロジェクトのビルドパスにある別のフォルダーにアセットを配置します。Flex コンパイラーによって Embed メタデータタグが検出されると、埋め込みアセットクラスが作成されます。このクラスには、[Embed] メタデータタグの直後に宣言するデータ型クラスの変数からアクセスします。例えば、次のコードでは sound1.mp3and というサウンドを埋め込み、soundCls という変数を使用して、そのサウンドに関連付けられている埋め込みアセットクラスに参照を保存します。 次に、埋め込みアセットクラスのインスタンスを作成して、そのインスタンスの play() メソッドを呼び出します。

package 
{ 
    import flash.display.Sprite; 
    import flash.media.SoundChannel; 
    import mx.core.SoundAsset; 
 
    public class SoundAssetExample extends Sprite 
    { 
        [Embed(source="sound1.mp3")] 
        public var soundCls:Class; 
         
        public function SoundAssetExample() 
        { 
            var mySound:SoundAsset = new soundCls() as SoundAsset; 
            var sndChannel:SoundChannel = mySound.play(); 
        } 
    } 
}

Adobe Flash Builder

Flash Builder ActionScript プロジェクトで [Embed] メタデータタグを使用するには、Flex フレームワークから必要なクラスをインポートする必要があります。例えば、サウンドを埋め込むには、mx.core.SoundAsset クラスのインポートが必要です。Flex フレームワークを使用するには、ActionScript ビルドパスに framework.swc ファイルを含めます。これによって SWF ファイルのサイズが増大します。

Adobe Flex

または、Flex 上で MXML タグ定義の @Embed() ディレクティブを使用してアセットを埋め込むこともできます。