みんながクラス名を適当につけていたら、名前がダブることがあるでしょう。
そういう名前の衝突を避けるために名前空間という機構が用意されています。
namespace.js
-------------------------------------------------------------------
//この元ネタを知っている人がいる確率は非常に低いと思われる
//元ネタが何か分かる人はいるかもしれないけど
import System;
import NS1; //パッケージをimport
var ayumi : NS1.CMargarita = new NS1.CMargarita();
var asami : NS1.CCappuccino = new NS1.CCappuccino();
Console.WriteLine("ayumiのはきものは" + ayumi.Footware());
Console.WriteLine("asamiのはきものは" + asami.Footware());
//パッケージ
package NS1 {
class CMargarita {
function Footware() : String { return "ピンヒール"; }
}
class CCappuccino {
function Footware() : String { return "ペタンコサンダル"; }
}
}
まず、
packageの中に
クラス・インターフェイス・列挙型を定義してパッケージ化します。
package NS1 {
class CMargarita {
...
}
...
}
ここではNS1がパッケージ名となります。
パッケージをインポートすると、
そのパッケージ内にパッケージ名付きでアクセスできるようになります。
import NS1;
var ayumi : NS1.CMargarita = new NS1.CMargarita();
名前の衝突がない場合は、パッケージ名を省略することができます。
上の例は、
var ayumi : CMargarita = new CMargarita();
var asami : CCappuccino = new CCappuccino();
でも問題なく動きます。
パッケージを複数インポートしているときは、
先にインポートした方は省略できます。
namespace2.js
--------------------------------------------------------------
import System;
import NS1;
import NS2;
var ayumi : C = new C(); //NS1を先にimportしたので省略できる
var asami : NS2.C = new NS2.C();
Console.WriteLine("ayumiのコードネームは" + ayumi.codename());
Console.WriteLine("asamiのコードネームは" + asami.codename());
package NS1 {
class C {
function codename() : String { return "夕張"; }
}
}
package NS2 {
class C {
function codename() : String { return "紺魚"; }
}
}
インポートの順番を逆にすると、
import NS2;
import NS1;
var ayumi : NS1.C = new NS1.C();
var asami : C = new C(); //NS2を省略できる
となります。
パッケージは入れ子にはできないのですが、
パッケージ名を
NS1.NS2
のようにすることによって入れ子のようにできます。
import System;
import NS1.NS2;
var asami : CCappuccino = new CCappuccino();
Console.WriteLine("asamiのコードネームは" + asami.codename());
//このパッケージはなくてもよい
package NS1 {
...
}
package NS1.NS2 {
class CCappuccino {
function codename() : String { return "紺魚"; }
}
}
あまり意味はなさそうですが、
C#やVB.Netでは入れ子にできるので、
それの代替手段ということなのでしょう。
パッケージ内でクラスやメンバに
internal修飾子を付すと、
パッケージ内のみで参照できることになります。
import System;
import NS1;
var asami : C = new C("たらふく");
Console.WriteLine(asami.speak()); //エラー
var asami2 : C2 = new C2("たらふく");
Console.WriteLine(asami2.speak()); //こちらはOK
package NS1 {
class C {
var chara : String;
function C(c : String) { chara = c; }
internal function speak() : String {
return chara + "番長じゃい!";
}
}
class C2 {
var c : C;
function C2(c2 : String) { c = new C(c2); }
function speak() : String {
return c.speak(); //内部から参照
}
}
}
外部から参照するとエラーが出ます。
2番目の例のパッケージ部分をライブラリにしてみましょう。
次のようにコンパイルするとDLLファイルが作成されます。
>jsc /target:library TSB.js
あるいは、
>jsc /t:library TSB.js
とします。こうすると、TSB.dllというファイルが作成されます。
TSB.js
-------------------------------------------------------
package NS1 {
class C {
function codename() : String { return "夕張"; }
}
}
package NS2 {
class C {
function codename() : String { return "紺魚"; }
}
}
これをインポートして次のようにコンパイルします。
>jsc /reference:TSB.dll namespace3.js
あるいは、
>jsc /r:TSB.dll namespace3.js
とします。こうすると、2番目の例と同じ動作をする.exeファイルが作られます。
namespace3.js
--------------------------------------------------------------
import System;
import NS1;
import NS2;
var ayumi : C = new C();
var asami : NS2.C = new NS2.C();
Console.WriteLine("ayumiのコードネームは" + ayumi.codename());
Console.WriteLine("asamiのコードネームは" + asami.codename());