名前空間では、作成したプロパティおよびメソッドの可視性を制御することができます。
public
、
private
、
protected
、および
internal
アクセス制御指定子は、ビルトイン名前空間のようなものです。これらのあらかじめ定義されているアクセス制御指定子が要件を満たさない場合は、独自の名前空間を作成することができます。
ActionScript 実装のシンタックスおよび詳細は XML とは少し異なりますが、XML 名前空間を使い慣れていれば、ここでの説明は新しいものではないかもしれません。 これまで名前空間を操作したことがない場合は、概念自体は単純ですが、その実装には特定の用語を習得する必要があります。
名前空間の操作を理解するには、プロパティまたはメソッドの名前に識別子と名前空間の 2 つの部分があることを認識することが役立ちます。 識別子は名前のようなものと考えることができます。 例えば、次のクラス定義の識別子は
sampleGreeting
と
sampleFunction()
です。
class SampleCode
{
var sampleGreeting:String;
function sampleFunction () {
trace(sampleGreeting + " from sampleFunction()");
}
}
定義の前に名前空間属性がない場合、名前は常にデフォルトの
internal
名前空間によって修飾されます。つまり、名前は同じパッケージの呼び出し元だけに表示されます。コンパイラーが strict モードに設定されている場合は、名前空間属性を変更せずに
internal
名前空間がすべての識別子に適用されることを示す警告がコンパイラーから出されます。識別子をどこでも使用できるようにするには、識別子名の前に
public
属性を付ける必要があります。前のコード例では、
sampleGreeting
と
sampleFunction()
の両方とも
internal
の名前空間値を持ちます。
名前空間を使用するときは、次の 3 つの手順に従います。 最初に、
namespace
キーワードを使用して名前空間を定義する必要があります。例えば、次のコードは、
version1
名前空間を定義します。
namespace version1;
次に、プロパティまたはメソッドの宣言でアクセス制御指定子の代わりに使用して、名前空間を適用します。 次の例では、
myFunction()
という関数を
version1
名前空間に配置します。
version1 function myFunction() {}
最後に、名前空間を適用すると、
use
ディレクティブを使用するか、識別子の名前を名前空間で修飾して参照できるようになります。次の例では、
use
ディレクティブから
myFunction()
関数を参照します。
use namespace version1;
myFunction();
次の例に示すように、修飾名を使用して
myFunction()
関数を参照することもできます。
version1::myFunction();
名前空間の定義
名前空間には、名前空間名とも呼ばれる URI(Uniform Resource Identifier)という値が含まれます。URI によって、名前空間定義を一意にすることができます。
次のいずれかの方法で名前空間定義を宣言して、名前空間を作成します。 XML 名前空間を定義するように、明示的な URI で名前空間を定義することも、URI を省略することもできます。 次の例では、URI を使用して名前空間を定義する方法を示します。
namespace flash_proxy = "http://www.adobe.com/flash/proxy";
URI は、その名前空間の一意の識別ストリングとして機能します。 次の例のように URI を省略した場合、コンパイラーは URI の代わりに一意の内部 ID ストリングを作成します。この内部 ID ストリングにはアクセスできません。
namespace flash_proxy;
名前空間を定義すると、URI の有無に関わらず、その名前空間は同じスコープ内で再定義することはできません。 同じスコープ内で以前に定義された名前空間を定義しようとすると、コンパイルエラーが発生します。
名前空間がパッケージまたはクラス内で定義された場合は、適切なアクセス制御指定子が使用されていなければ、名前空間はそのパッケージまたはクラスの外部にあるコードに対して表示されません。 例えば、次のコードは flash.utils パッケージ内で定義された
flash_proxy
名前空間を示します。次の例で、アクセス制御指定子が存在しないことは、
flash_proxy
名前空間が flash.utils パッケージ内のコードだけに表示され、パッケージ外のコードからは参照できないことを意味します。
package flash.utils
{
namespace flash_proxy;
}
次のコードは、
public
属性を使用して、
flash_proxy
名前空間がパッケージ外のコードから参照できるようにします。
package flash.utils
{
public namespace flash_proxy;
}
名前空間の適用
名前空間を適用するとは、名前空間に定義を配置することです。 名前空間に配置できる定義には、関数、変数、および定数があります。カスタム名前空間にクラスを配置することはできません。
例えば、
public
アクセス制御名前空間で宣言された関数があるとします。関数定義に
public
属性を使用すると、関数はパブリックの名前空間に配置され、すべてのコードで利用できるようになります。名前空間を定義した後は、
public
属性を使用する場合と同じように使用でき、カスタム名前空間を参照可能なコードでその名前空間定義を使用できるようになります。例えば、次の例に示すように、名前空間
example1
を定義すると、
example1
を属性として使用して
myFunction()
というメソッドを追加できます。
namespace example1;
class someClass
{
example1 myFunction() {}
}
名前空間
example1
を属性として使用して
myFunction()
メソッドを宣言することは、メソッドが
example1
名前空間に属することを意味します。
名前空間を適用する際には、次の点に注意してください。
-
適用できる名前空間は宣言ごとに 1 つだけです。
-
名前空間属性を一度に複数の定義に適用することはできません。 つまり、10 個の異なる関数に名前空間を適用する場合、10 個の異なる関数それぞれに名前空間を属性として追加する必要があります。
-
名前空間とアクセス制御指定子は相互に排他的であるため、名前空間を適用すると、アクセス制御指定子を指定することはできません。 つまり、名前空間を適用すると、
public
、
private
、
protected
、または
internal
として関数またはプロパティを宣言することはできません。
名前空間の参照
public
、
private
、
protected
、
internal
などのアクセス制御名前空間で宣言されたメソッドまたはプロパティを使用するとき、名前空間を明示的に参照する必要はありません。このような特別な名前空間へのアクセスはコンテキストによって制御されるからです。 例えば、
private
名前空間に配置された定義は、自動的に同じクラス内のコードで利用できるようになります。しかし、定義した名前空間では、こうした状況依存性は存在しません。 カスタム名前空間に配置したメソッドまたはプロパティを使用するには、その名前空間を参照する必要があります。
use namespace
ディレクティブで名前空間を参照できます。また、名前修飾子(
::
)を使用して名前空間で名前を修飾できます。
use namespace
ディレクティブで名前空間を参照すると、修飾されていない識別子に名前空間を適用できるように、名前空間が開きます。例えば、
example1
名前空間を定義している場合、
use namespace example1
を使用して、その名前空間内の名前にアクセスすることができます。
use namespace example1;
myFunction();
一度に複数の名前空間を開くことができます。
use namespace
で名前空間を開くと、名前空間はそれ自体が開かれたコードブロック全体で開かれたままになります。名前空間を明示的に閉じることはできません。
しかし、複数の名前空間を開くと、名前のコンフリクトが起こりやすくなります。 名前空間を開かない場合は、メソッドまたはプロパティの名前を名前空間と名前修飾子で修飾すると、
use namespace
ディレクティブを使用する必要はありません。例えば、次のコードは、
example1
名前空間で名前
myFunction()
を修飾する方法を示します。
example1::myFunction();
名前空間の使用
ActionScript 3.0 の一部である flash.utils.Proxy クラス内に名前の競合を避けるために使用されている名前空間の実際の例を見つけることができます。Proxy クラスは、ActionScript 2.0 の
Object.__resolve
プロパティの代替クラスであり、エラーが発生する前に未定義のプロパティまたはメソッドへの参照を取得します。Proxy クラスのすべてのメソッドは、名前の競合を避けるため
flash_proxy
名前空間に置かれます。
flash_proxy
名前空間の使用方法についての理解を深めるために、Proxy クラスの使用方法を理解する必要があります。Proxy クラスの機能は、Proxy クラスを継承するクラスでのみ使用できます。 つまり、オブジェクト上で Proxy クラスのメソッドを使用する場合、そのオブジェクトのクラス定義は Proxy クラスを拡張する必要があります。例えば、未定義のメソッドへの呼び出しの試みを取得する場合、Proxy クラスを拡張し、Proxy クラスの
callProperty()
メソッドをオーバーライドします。
名前空間の実装には通常、名前空間の定義、適用、および参照の 3 つの手順を実行します。 しかし、Proxy クラスのメソッドを明示的に呼び出していないため、
flash_proxy
名前空間は定義および適用されるだけで、参照されません。ActionScript 3.0 では、
flash_proxy
名前空間を定義し、これを Proxy クラス内に適用します。コードは、
flash_proxy
名前空間を Proxy クラスを拡張するクラスに適用するだけです。
flash_proxy
名前空間は、次のような方法で flash.utils パッケージで定義されます。
package flash.utils
{
public namespace flash_proxy;
}
次の Proxy クラスからの抜粋に示すように、名前空間が Proxy クラスのメソッドに適用されます。
public class Proxy
{
flash_proxy function callProperty(name:*, ... rest):*
flash_proxy function deleteProperty(name:*):Boolean
...
}
次のコードに示すように、まず Proxy クラスと
flash_proxy
名前空間の両方を読み込む必要があります。次に、Proxy クラスを拡張するようにクラスを宣言する必要があります。strict モードでコンパイルしている場合は、
dynamic
属性を追加する必要もあります。
callProperty()
メソッドをオーバーライドするときは、
flash_proxy
名前空間を使用する必要があります。
package
{
import flash.utils.Proxy;
import flash.utils.flash_proxy;
dynamic class MyProxy extends Proxy
{
flash_proxy override function callProperty(name:*, ...rest):*
{
trace("method call intercepted: " + name);
}
}
}
MyProxy クラスのインスタンスを作成し、次の例で呼び出される
testing()
メソッドなどの未定義のメソッドを呼び出すと、Proxy オブジェクトがメソッドの呼び出しを取得し、オーバーライドされた
callProperty()
メソッド内のステートメントを実行します(この場合は、単純な
trace()
ステートメント)。
var mySample:MyProxy = new MyProxy();
mySample.testing(); // method call intercepted: testing
flash_proxy
名前空間内に Proxy クラスのメソッドを配置すると、2 つの利点があります。1 つ目は、別の名前空間があると、Proxy クラスを拡張するクラスのパブリックインターフェイスを整理できます。 Proxy クラスには、オーバーライドできるメソッドが 10 個以上ありますが、これらのメソッドは直接呼び出せるように設計されていません。 これらすべてをパブリック名前空間に配置すると、混乱の元になります。 2 つ目は、Proxy サブクラスに Proxy クラスのメソッドと一致する名前のインスタンスメソッドが含まれている場合、
flash_proxy
名前空間を使用すると、名前のコンフリクトを回避することができます。例えば、独自のメソッド
callProperty()
に名前を付けるとします。この
callProperty()
メソッドは別の名前空間にあるため、次のコードは有効です。
dynamic class MyProxy extends Proxy
{
public function callProperty() {}
flash_proxy override function callProperty(name:*, ...rest):*
{
trace("method call intercepted: " + name);
}
}
名前空間は、4 つのアクセス制御指定子(
public
、
private
、
internal
、および
protected
)では実行できない方法でメソッドまたはプロパティにアクセスする場合にも便利です。例えば、複数のパッケージに分散するいくつかのユーティリティメソッドがあるとします。 これらのメソッドをパブリックにしないで、すべてのパッケージで利用できるようにするには、名前空間を作成して、独自のアクセス制御指定子として使用します。
次の例では、ユーザー定義の名前空間を使用して、異なるパッケージにある 2 つの関数をグループ化します。これらを同じ名前空間にグループ化することにより、両方の関数を 1 つの
use namespace
ステートメントを介してクラスまたはパッケージに表示することができます。
この例では、4 つのファイルを使用してその手法を示します。 ファイルはすべてクラスパス内にある必要があります。 1 つ目のファイル myInternal.as を使用して
myInternal
名前空間を定義します。このファイルは example パッケージにあるため、example という名前のフォルダーに配置する必要があります。 名前空間は
public
とマークされているので、他のパッケージに読み込むことができます。
// myInternal.as in folder example
package example
{
public namespace myInternal = "http://www.adobe.com/2006/actionscript/examples";
}
2 つ目と 3 つ目のファイル Utility.as と Helper.as は、他のパッケージで使用できるメソッドを含むクラスを定義します。 Utility クラスは example.alpha パッケージ内にあります。つまり、example フォルダーのサブフォルダーである alpha という名前のフォルダーにファイルを配置する必要があります。 Helper クラスは example.beta パッケージ内にあります。つまり、example フォルダーのサブフォルダーでもある beta という名前のフォルダーにファイルを配置する必要があります。 これらのパッケージ example.alpha と example.beta の両方とも名前空間を使用する前に読み込む必要があります。
// Utility.as in the example/alpha folder
package example.alpha
{
import example.myInternal;
public class Utility
{
private static var _taskCounter:int = 0;
public static function someTask()
{
_taskCounter++;
}
myInternal static function get taskCounter():int
{
return _taskCounter;
}
}
}
// Helper.as in the example/beta folder
package example.beta
{
import example.myInternal;
public class Helper
{
private static var _timeStamp:Date;
public static function someTask()
{
_timeStamp = new Date();
}
myInternal static function get lastCalled():Date
{
return _timeStamp;
}
}
}
4 つ目のファイル "NamespaceUseCase.as" は、メインアプリケーションクラスで、example フォルダーと兄弟関係になければなりません。 Flash Professional では、このクラスは FLA の document クラスとして使用されます。 NamespaceUseCase クラスも
myInternal
名前空間を読み込み、この名前空間を使用して、他のパッケージにある 2 つの静的メソッドを呼び出します。この例では、コードを簡略化するためにのみ静的メソッドを使用します。 静的メソッドおよびインスタンスメソッドは両方とも
myInternal
名前空間に配置することができます。
// NamespaceUseCase.as
package
{
import flash.display.MovieClip;
import example.myInternal; // import namespace
import example.alpha.Utility;// import Utility class
import example.beta.Helper;// import Helper class
public class NamespaceUseCase extends MovieClip
{
public function NamespaceUseCase()
{
use namespace myInternal;
Utility.someTask();
Utility.someTask();
trace(Utility.taskCounter); // 2
Helper.someTask();
trace(Helper.lastCalled); // [time someTask() was last called]
}
}
}