名前空間名前空間(なまえくうかん、英: namespace / name-space)は、名前の集合を分割することで衝突の可能性を低減しつつ参照を容易にする概念である。 この集合は、全事象の元の全ての組み合わせ可能なものからなる集合全体および物理的な名称を指すことが可能である。つまり英字・数字・記号などを組みあわせて作られる名前全てを含む集合である。名前に結び付けられる実体(型や変数や関数)は、名前がそれぞれどの集合(空間)に属するか指定されることで一意に定まる。名前空間が異なれば同じ名前でも別の実体に対応付けられる。 身近な類似例
たとえば「一郎」という人名は日本中に何人もいるため、ひとりの人間に特定することはできない。このように、同一の名前のものが複数存在し、その区別がつかない状態を名前の衝突(名前の競合)と呼ぶ。しかし、「鈴木一郎」とフルネームで呼ぶことにより他の「佐藤一郎」や「山本一郎」といった人とは区別でき、名前の衝突を避けることができる。このとき「一郎」を単純名、「鈴木一郎」を完全限定名と呼ぶ。[独自研究?]人名「一郎」は名前空間「鈴木」に属していると捉えることができる。また、同じ「鈴木」という姓である鈴木家の家族間では、「一郎」は暗黙的に「鈴木一郎」のことであると解釈されるため、わざわざ完全限定名の「鈴木一郎」で呼ぶ必要がない。また、予め「『一郎』とは『鈴木一郎』のことである」と宣言しておけば、その後単純名で「一郎」と呼んでも暗黙的に「鈴木一郎」だと解釈されるため、シンプルな「一郎」のみで呼ぶことができる。必要なら、「日本国東京都世田谷区○丁目○○鈴木一郎」と呼ぶことで、同姓同名の人間とも区別することができる[注釈 1]。これらの考え方は名前空間の概念に近いものである(これは分かりやすく説明するための方便であり、名前空間とは厳密にはイコールではない)。 プログラミング
コンピュータプログラミングにおける名前空間は、ソースコード上で冗長な命名規則を用いなくても名前の衝突が起こらないようにし、しかもそれを容易に記述できるようにするためだけの概念であり、普通はそれ以上の意味は持っていない(上記の地名のたとえは行政上の管轄としての意味合いがあるが、プログラミング言語の名前空間には一意な名前という以上の意味合いはない)。Javaの機能、「パッケージ」では名前空間とアクセス制限、ソースファイルのディレクトリ構造の表現の機能を統合しているが、C++やC#の「純粋な」名前空間はクラスやそのメンバのアクセス制限とは無関係である。Cには名前空間を複数に分割する機能が無く、名前の衝突を避けるためにはなんらかの命名規則を用いる必要がある。 通常は文脈によって定まる名前空間が暗黙に指定される。指定したい実体に対応する名前が他の名前空間にある場合は、名前空間と名前を明示的に組み合わせることで一意に特定できる。たとえば名前 同一のスコープに、異なる種別の構文要素で同じ名前(識別子)が出現する場合、文脈で区別する言語もある。 以下はJavaの例である。 public class SomeClass {
void baz() { System.out.println("baz() is called."); }
int baz;
public void doSomething1() {
baz();
}
public void doSomething2() {
baz = 100;
}
}
この例では同じ しかし、ひとつの名前空間の中で同名の型/同名の変数/同名の関数を複数定義すると問題が発生する。次の疑似コードのように、同じ名前の関数、Hogeを2つ定義したとする。 void Hoge() {} void Hoge() {} void Main() { Hoge(); } この場合、2つ目のHoge関数が定義された時点で、処理系は多重定義としてエラーを出す。特に複数のチームで開発を行っていると名前の衝突が起きやすい。次の例は、別々のチームで書かれた2つの関数Hoge()の名前の衝突を避けるため、関数名の先頭に「チーム名_」とつけるように取り決めた場合のものである。 void TeamA_Hoge() {} void TeamB_Hoge() {} void Main() { TeamA_Hoge(); TeamB_Hoge(); } これでも名前の衝突は避けられるが、呼び出しでは常にチーム名まで含めた名称で記述しなければならないため、記述も面倒でソースコードは読みにくくなってしまう。また、両方の関数をincludeしないような時には名前の衝突は起こらず、せっかくの命名規則も取り越し苦労に終わってしまう。このような場合は、2つのクラスHogeを別々の名前空間に入れる。 namespace TeamA { void Hoge() {} } namespace TeamB { void Hoge() {} } void Main() { TeamA.Hoge(); TeamB.Hoge(); } こうすると、上の関数Hogeの名前はTeamA.Hoge、下の関数Hogeの名前はTeamB.Hogeとなり、両者を区別できるようになる。複数のチームで開発を行う場合は、チームごとに使用する名前空間を決めておけば名前の衝突は起こらないので、それぞれのチームが自由に名前を付けることができる。しかし、ひとつのソースコード中でTeamA.HogeとTeamB.Hogeの片方だけを使う場合は、完全限定名での記述は冗長な表現となってしまう。以下の疑似コードでは、 using namespace TeamA; void Main() { Hoge(); } 処理系は namespace TeamA { void Hoge() {} void Main() { Hoge(); // TeamA.Hogeの呼び出しだとみなされる } } オーバーロードをサポートする言語であれば、引数などのインターフェイスが異なる場合に限り、異なる関数や異なるメソッドに同じ名前を使用することができる。どのオーバーロードが使用されるかは、呼び出し時に渡す実引数の型などから文脈によって判断される。 プログラミング以外の名前空間これら名前空間およびそれに付随する概念は、プログラミング言語に限らず活用されている。例えば、EメールアドレスやURIも名前空間と同等の論理で組み立てられていることはよく知られており、このような命名の仕組みによって名前を区別、分類するようなものを、広く名前空間と呼ぶこともある。
脚注注釈
出典
関連項目 |
Portal di Ensiklopedia Dunia