前回の記事で public 宣言された関数を名前空間を使って上書きできる云々を書きましたが、このことから推測できるように public も名前空間です。実際に public の別名を作ることもできます。
public static namespace myNS1 = public;
public に限らずアクセス修飾子は全て名前空間として扱われます。この辺りから、なぜ EcmaScript4 のプロポーザルでは protected の実装が必要ないと判断されたかなんとなく想像できそうですね。
オープンな名前空間には、明示的に宣言していなくても public, internal, protected, private は予め含まれています。そのために public や private 宣言された属性の参照に public:: 等をつける必要が無かったわけです。
インスタンス属性の修飾名による参照
ここで、ちょっと寄り道をして、インスタンスの属性を参照するときの名前空間の指定方法について説明します。
まず、以下のような名前空間&クラス定義があるとします。
myNS1.as: public namespace myNS1 myNS2.as: public namespace myNS2 SampleClass.as: public class SampleClass { myNS1 var foo:int = 0; myNS2 var foo:int = 1; }
この場合 SampleClass のインスタンスから foo を参照する際は名前空間を意識しなくてはなりません。属性参照時に明示的に名前空間を指定するには以下のように記述します。
var sc:SampleClass = new SampleClass(); sc.myNS1::foo = 100;
また、名前空間の指定に変数を使用することもできます。変数の型は Namespace になります。
var sc:SampleClass = new SampleClass(); var ns:Namespace = myNS1; sc.ns::foo = 100;
名前空間によるアクセス制御の例
さて、準備もできたので、ここで名前空間を使ったアクセス制御の例を紹介します。C++ のフレンド関数もどきの機能を実現してみたいと思います。
public class WithSecret { private static namespace mySecretNS; // アクセスを許可するクラス名を設定 private var myFriend:Object = MyFriend; public function checkFriend(target:Object):Namespace { if(target is myFriend) { return mySecretNS; } else { return null; } } // プライベートな名前空間に関数を定義 myNS function secretFunction():Void { trace("this is my secret"); } }
クラス WithSecret には mySecretNS という名前空間に定義した関数 secretFunction があります。mySecretNS はプライベートな名前空間なので、他のクラスから直接指定することはできません。つまり secretFunction は事実上「見えない」関数になっています。
一方、特定のクラス(この例では MyFriend クラス)のインスタンスに対してのみ mySecretNS を返す関数も実装されています。受け取ったインスタンスは mySecretNS を指定できるため、以下のようにして秘密の関数を呼び出すことができます。
public class MyFriend { public function getSecret(obj:WithSecret) { var ns:Namespace = obj.checkFriend(this); if(ns != null) { obj.ns::secretFunction(); } } }
コメントする