| ActionScript 3.0 のプログラミング > ActionScript プログラミングの概要 > ActionScript のオブジェクト指向プログラミング > クラス > メソッド | |||
メソッドは、クラス定義の一部である関数です。クラスのインスタンスが作成されると、メソッドはそのインスタンスにバインドされます。クラス外で宣言された関数とは異なり、メソッドは関連付けられているインスタンスと別々に使用することはできません。
メソッドは、function キーワードを使用して定義します。次のような関数ステートメントを使用できます。
public function sampleFunction():String {}
または、次のように関数式を割り当てる変数を使用することもできます。
public var sampleFunction:Function = function () {}
通常は、次のような理由から関数式ではなく関数ステートメントを使用します。
override および final キーワードを使用できます。詳細については、メソッドのオーバーライドを参照してください。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); // 出力 : initialized
コンストラクタメソッドにはパブリックしか指定できませんが、public 属性を使用するかどうかは任意です。コンストラクタに、private、protected、internal やその他のアクセス制御指定子を使用することはできません。また、ユーザー定義の名前空間をコンストラクタメソッドと使用することもできません。
コンストラクタは、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(); // 出力 : 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); // 出力 : 2
}
}
インスタンスメソッドの本体内にある this 参照の値は、メソッドが関連付けられているインスタンスへの参照です。次のコードは、this 参照がメソッドを含むインスタンスを参照していることを示します。
class ThisTest
{
function thisValue():ThisTest
{
return this;
}
}
var myTest:ThisTest = new ThisTest();
trace(myTest.thisValue() == myTest); // true
インスタンスメソッドの継承は、override と final のキーワードを使用して制御できます。override 属性を使用して継承されたメソッドを定義できます。また、final 属性を使用すると、サブクラスによってメソッドがオーバーライドされないようにできます。詳細については、メソッドのオーバーライドを参照してください。
"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); // エラーが発生する
GetSet クラスを使用している場合は、publicAccess というプロパティのように見える、privateProperty というプライベートプロパティに対して動作する get と set のアクセサ関数の組み合わせを使用します。次の例では、GetSet クラスをインスタンス化し、publicAccess というパブリックアクセサを使用して privateProperty の値を設定します。
var myGetSet:GetSet = new GetSet(); trace(myGetSet.publicAccess); // null myGetSet.publicAccess = "hello"; trace(myGetSet.publicAccess); // 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 // 定義されたバインドメソッド
{
trace("foo's this: " + this);
trace("num: " + num);
}
function bar():Function
{
return foo; // 返されたバインドメソッド
}
}
var myTest:ThisTest = new ThisTest();
var myFunc:Function = myTest.bar();
trace(this); // 出力 : [object global]
myFunc();
/* 出力 :
foo's this: [object ThisTest]
num: 3 */
コードの最後の 2 行は、バインドメソッド foo() の this 参照が、その直前の行の this 参照がグローバルオブジェクトを指していても、依然として ThisTest クラスのインスタンスを指すことを示しています。さらに、myFunc 変数に格納されているバインドメソッドは、引き続き ThisTest クラスのメンバー変数にアクセスすることができます。この同じコードを ActionScript 2.0 で実行すると、this 参照が一致し、num 変数は undefined になります。
addEventListener() メソッドでは関数またはメソッドをパラメータとして渡す必要があるため、バインドメソッドの追加が最もわかりやすいのはイベントハンドラを使用する場合です。詳細については、クラスメソッドとして定義したリスナー関数を参照してください。
Flex 2.01