コンピューティングにおいて、名前空間とは、さまざまな種類のオブジェクトを識別および参照するために使用される一連の記号 (名前) です。名前空間により、特定のオブジェクト セットのすべてが一意の名前を持つようになり、簡単に識別できるようになります。
名前空間は、通常、異なるコンテキストで名前を再利用できるように階層構造になっています。類推として、各人が名を持ち、親戚と共有する姓を持つ人の命名システムを考えてみましょう。家族のメンバーのファーストネームが各家族内でのみ一意である場合、各人はファーストネームと姓の組み合わせで一意に識別できます。ジェーン・ドウは 1 人だけですが、ジェーンは複数存在する可能性があります。ドウ家の名前空間内では、この人物を明確に指定するには「ジェーン」だけで十分ですが、すべての人の「グローバル」名前空間内では、フルネームを使用する必要があります。
名前空間の代表的な例としては、ファイルに名前を割り当てるファイルシステムが挙げられます。[1] 一部のプログラミング言語では、変数やサブルーチンを名前空間で整理します。[2] [3] [4] コンピュータネットワークや分散システムは、コンピュータ、プリンタ、ウェブサイト、リモートファイルなどのリソースに名前を割り当てます。オペレーティングシステムは、仮想化コンテナをサポートするために、カーネルリソースを分離された名前空間で分割することができます。
同様に、階層型ファイル システムでは、ファイルをディレクトリに整理します。各ディレクトリは個別の名前空間であるため、ディレクトリ「letters」と「invoices」の両方にファイル「to_jane」が含まれる場合があります。
コンピュータ プログラミングでは、名前空間は通常、特定の機能を中心にシンボルと識別子をグループ化し、同じ名前を共有する複数の識別子間の 名前の衝突を回避するために使用されます。
ネットワークでは、ドメイン ネーム システムがWeb サイト (およびその他のリソース) を階層型の名前空間に編成します。
名前の競合
要素名は開発者によって定義されます。このため、異なる XML アプリケーションの XML ドキュメントを混在させようとすると、競合が発生することがよくあります。
この XML はHTML テーブル情報を保持します。
<table>
<tr> <td>リンゴ</td> <td>オレンジ</td> </tr> </table>
この XML はテーブル(つまり家具) に関する情報を伝えます。
<table>
<name>マホガニーコーヒーテーブル</name> <width> 80 </width> <length> 120 </length> </table>
これらの XML フラグメントを追加すると、名前の競合が発生します。どちらにも<table>...</table>要素が含まれていますが、要素の内容と意味が異なります。
XML パーサーはこれらの違いをどのように処理するかを知りません。
プレフィックスによる解決
XML 内の名前の競合は、名前プレフィックスを使用することで簡単に回避できます。
次の XML は、要素の先頭に「h」と「f」をプレフィックスとして付けることで、HTML テーブルと家具に関する情報を区別します。
<h:table>
<h:tr> <h:td>リンゴ</h:td> <h:td>オレンジ</h:td> </h:tr> </h:table>
<f:table>
<f:name>マホガニーコーヒーテーブル</f:name> <f:width> 80 </f:width> <f:length> 120 </f:length> </f:table>
命名システム
名前空間内の名前は、名前空間名とローカル名で構成されます。[5] [6]名前空間名は通常、ローカル名の プレフィックスとして適用されます。
拡張バッカス・ナウア形式では:
name = <名前空間名>セパレータ<ローカル名>
ローカル名が単独で使用される場合、名前解決を使用して、特定のローカル名によって参照される特定の名前 (存在する場合) を決定します。
例
委任
当事者間の責任の委任は、ワールドワイドウェブの構造など、現実世界のアプリケーションにおいて重要です。名前空間により、グローバルな一意性を維持しながら、複数の名前発行組織に識別子の割り当てを委任できます。[8]中央登録機関は、割り当てられた名前空間名を登録します。各名前空間名は、割り当てられた名前空間内の名前の割り当てに責任を負う組織に割り当てられます。この組織は、名前を自分で割り当てる名前発行組織の場合もあれば、名前空間の一部を別の組織にさらに委任する別の登録機関の場合もあります。
階層
名前空間を第三者に再委任できる命名スキームは、階層型名前空間です。
名前空間名の構文が各サブ委任で同じである場合、階層は再帰的です。再帰階層の例としては、ドメイン ネーム システムがあります。
非再帰階層の例としては、Internet Assigned Numbers Authority (IANA) 番号を表すUniform Resource Nameがあります。
名前空間とスコープ
名前空間名は、名前にコンテキスト (コンピューター サイエンスではスコープ) を提供する場合があり、これらの用語は互換的に使用されることがあります。ただし、名前のコンテキストは、名前が出現する場所や名前の構文など、他の要因によって提供される場合もあります。
プログラミング言語では
多くのプログラミング言語では、名前空間は識別子のコンテキストです。オペレーティングシステムでは、名前空間の例としてはディレクトリがあります。ディレクトリ内の各名前は、1つのファイルまたはサブディレクトリを一意に識別します。[9]
原則として、名前空間内の名前は複数の意味を持つことはできません。つまり、同じ名前空間内で異なる意味を持つ名前が同じ名前を共有することはできません。名前空間はコンテキストとも呼ばれます。異なる名前空間内の同じ名前は、それぞれの名前空間に適した異なる意味を持つことができるためです。
名前空間のその他の特性は次のとおりです。
- 名前空間内の名前は、概念だけでなくオブジェクトも表すことができます。名前空間は、自然言語や民族言語、人工言語、専門分野の技術用語、方言、社会方言、人工言語 (プログラミング言語など) などです。
- Java プログラミング言語では、名前空間に現れる識別子には、短い (ローカル) 名と、名前空間外で使用するための一意の長い「修飾」名があります。
- 一部のコンパイラ( C++などの言語用)は、名前マングリングと呼ばれるプロセスで、コンパイラ内で内部使用するために名前空間と名前を結合します。
上で説明した抽象的な言語の技術的な使用法に加えて、一部の言語には、明示的な名前空間の制御に使用される特定のキーワードなどもあります。以下は、C++ の名前空間の例です。
#include <iostream>
// これは、名前を現在のスコープに持ち込む方法です。この場合、// グローバル スコープに持ち込みます。using
std :: cout ; using std :: endl ;
名前空間box1 { int box_side = 4 ; }
名前空間box2 { int box_side = 12 ; }
int main () { int box_side = 42 ; cout << box1 :: box_side << endl ; // 4 を出力します。cout << box2 :: box_side << endl ; // 12 を出力します。cout << box_side << endl ; // 42 を出力します。}
コンピュータサイエンスの考察
コンピュータサイエンスにおける名前空間(名前スコープとも呼ばれる)は、一意の識別子またはシンボル(つまり名前)の論理的なグループを保持するために作成された抽象的なコンテナまたは環境です。名前空間で定義された識別子は、その名前空間にのみ関連付けられます。同じ識別子を複数の名前空間で個別に定義できます。つまり、1つの名前空間で定義された識別子は、別の名前空間で定義された同じ識別子と同じ意味を持つことも、そうでないこともあります。名前空間をサポートする言語は、識別子(その定義ではなく)がどの名前空間に属するかを決定するルールを指定します。[10]
この概念は、アナロジーで説明できます。2 つの会社 X と Y がそれぞれ従業員に ID 番号を割り当てているとします。X には 2 人の従業員が同じ ID 番号を持つべきではなく、Y についても同様です。ただし、両方の会社で同じ ID 番号を使用することは問題ありません。たとえば、ビルが会社 X で働き、ジェーンが会社 Y で働いている場合、2 人とも従業員番号 123 であっても問題ありません。このアナロジーでは、ID 番号が識別子であり、会社が名前空間として機能します。同じ識別子が各名前空間で異なる人物を識別しても、問題は発生しません。
大規模なコンピュータ プログラムやドキュメントでは、数百または数千の識別子が存在するのが一般的です。名前空間 (または同様の手法、名前空間のエミュレートを参照) は、ローカル識別子を非表示にするメカニズムを提供します。名前空間は、論理的に関連する識別子を対応する名前空間にグループ化する手段を提供し、それによってシステムをよりモジュール化します。
データ ストレージ デバイスと多くの最新のプログラミング言語は、名前空間をサポートしています。ストレージ デバイスは、ディレクトリ (またはフォルダー) を名前空間として使用します。これにより、異なるディレクトリに保存されている限り、同じ名前の 2 つのファイルをデバイスに保存できます。一部のプログラミング言語 ( C++、Pythonなど) では、名前空間を指定する識別子自体が、囲む名前空間に関連付けられています。したがって、これらの言語では、名前空間がネストされ、名前空間ツリーを形成できます。このツリーのルートは、名前のないグローバル名前空間です。
共通言語での使用
C
C99以降、Cでは匿名構造体を名前空間として使用できるようになりました。
// helper.c
static int _add ( int a 、int b ) { return a + b ; }
const構造体{ double pi ; int ( * add ) ( int 、int ); }ヘルパー= { 3.14 、_add };
// helper.h
const struct { double pi ; int ( * add ) ( int , int ); } helper ;
// main.c
#include <stdio.h> #include "helper.h"
int main (){ printf ( "3 + 2 = %d \n " , helper . add ( 3 , 2 )); printf ( "pi is %f \n " , helper . pi ); }
C++
C++では、名前空間は名前空間ブロックで定義されます。[11]
名前空間abc { int bar ; }
このブロック内では、識別子は宣言されたとおりに使用できます。このブロックの外では、名前空間指定子をプレフィックスとして付ける必要があります。たとえば、 の外ではnamespace abc、アクセスするには とbar記述する必要がありますabc::bar。C++ には、この冗長性を不要にする別の構造があります。次の行を追加することで、
名前空間abc を使用します。
コードの一部にプレフィックスを追加すると、プレフィックスabc::は不要になります。
名前空間内で明示的に宣言されていない識別子は、グローバル名前空間内にあると見なされます。
整数foo ;
これらの識別子は宣言されたとおりに使用することもできますが、グローバル名前空間には名前が付いていないため、名前空間指定子::をプレフィックスとして付けることもできます。たとえば、 はfooと書くこともできます::foo。
C++ における名前空間の解決は階層的です。つまり、仮想名前空間 内ではfood::soup、識別子 はchickenを参照しますfood::soup::chicken。food::soup::chickenが存在しない場合は を参照しますfood::chicken。 も も存在しない場合はfood::soup::chicken、food::chickenはグローバル名前空間内の識別子
chickenを参照します。::chicken
C++ の名前空間は、名前の衝突を避けるために最もよく使用されます。名前空間は最近の C++ コードで広範に使用されていますが、ほとんどの古いコードでは、言語の初期のバージョンには存在しなかったため、この機能は使用されていません。たとえば、C ++ 標準ライブラリ全体は内で定義されていますnamespace stdが、標準化される前は、多くのコンポーネントがもともとグローバル名前空間にありました。プログラマは、usingディレクティブを挿入して名前空間解決の要件をバイパスし、すべての識別子がグローバル名前空間にあることを想定している古いコードとの下位互換性を確保できます。ただし、下位互換性以外の理由 (利便性など) で ディレクティブを使用することusingは、適切なコード プラクティスに反すると見なされます。
ジャワ
Javaでは、名前空間の概念はJava パッケージに具体化されています。すべてのコードはパッケージに属しますが、そのパッケージに明示的に名前を付ける必要はありません。他のパッケージのコードにアクセスするには、適切な識別子の前にパッケージ名をプレフィックスとして付けます。たとえばclass String、 はとして参照できます(これは完全修飾クラス名と呼ばれます)。C++ と同様に、Java ではパッケージ名 ( ) を入力する必要がない構造が提供されています。ただし、特定の機能 (リフレクションなど) では、プログラマは完全修飾名を使用する必要があります。
package java.langjava.lang.Stringimport
C++ とは異なり、Java の名前空間は、言語の構文に関する限り階層的ではありません。ただし、パッケージは階層的に命名されます。たとえば、 で始まるすべてのパッケージはJava プラットフォームjavaの一部です。パッケージには、言語のコアとなるクラスと、リフレクションに特に関連するコア クラスが含まれています。
java.langjava.lang.reflect
Java (およびAda、C#など) では、名前空間/パッケージはコードの意味カテゴリを表します。たとえば、 C# では、namespace Systemシステム ( .NET Framework ) によって提供されるコードが含まれます。これらのカテゴリの具体的度合いと階層の深さは、言語によって異なります。
関数スコープとクラス スコープは、可視性、アクセシビリティ、オブジェクトの有効期間と密接に関連している暗黙の名前空間として見ることができます。
C#
名前空間はC#言語で頻繁に使用されます。すべての.NET Frameworkクラスは、より明確に使用し、混乱を避けるために名前空間に編成されています。さらに、カスタム名前空間は、作業を整理し、名前の衝突を避けるためにプログラマーによって広く使用されています。クラスを参照するときは、名前空間の後にクラス名が続く完全修飾名を指定する必要があります。
System.Console.WriteLine ( " Hello World ! " ) ; int i = System.Convert.ToInt32 ( " 123 " ) ;
またはusingステートメントを追加します。これにより、その名前空間内のすべてのクラスの完全な名前を指定する必要がなくなります。
システムの使用;
Console.WriteLine ( " Hello World!" ); int i = Convert.ToInt32 ( " 123 " ) ;
上記の例では、System は名前空間であり、ConsoleとConvert はSystem内で定義されたクラスです。
パイソン
Pythonでは、名前空間は個々のモジュールによって定義され、モジュールは階層的なパッケージに含めることができるため、名前空間も階層的です。[12] [13] 一般に、モジュールがインポートされると、モジュールで定義された名前はそのモジュールの名前空間を介して定義され、呼び出し元のモジュールから完全修飾名を使用してアクセスされます。
# modulea が 2 つの関数 (func1() と func2()) と 1 つのクラス (Class1) を定義していると仮定します
。import Modulea
Modulea.func1 ( ) Modulea.func2 ( ) a = Modulea.Class1 ( )
このfrom ... import ...ステートメントを使用すると、関連する名前を呼び出しモジュールの名前空間に直接挿入することができ、それらの名前には、修飾名なしで呼び出しモジュールからアクセスできます。
# Modulea が 2 つの関数 (func1() と func2()) と 1 つのクラス (Class1) を定義していると仮定します。
from Modulea import func1
func1 ()
func2 () # これは未定義の名前として失敗します。完全な名前 Modulea.func2() も同様です
。a = Class1 () # これは未定義の名前として失敗します。完全な名前 Modulea.Class1() も同様です。
これは名前を直接インポートするため (修飾なし)、警告なしで既存の名前を上書きする可能性があります。
ステートメントの特別な形式は、from ... import *指定されたパッケージで定義されているすべての名前を呼び出しモジュールの名前空間に直接インポートします。この形式のインポートの使用は、言語内でサポートされていますが、呼び出しモジュールの名前空間を汚染し、名前の衝突が発生した場合に既に定義されている名前が上書きされるため、一般的には推奨されません。[14]
Python は、import x as y呼び出しモジュールで使用するためのエイリアスまたは代替名を提供する方法として、以下もサポートしています。
numpyを npとして インポートする
a = np . arange ( 1000 )
XML名前空間
XMLでは、プログラミング言語における名前空間の役割と同様に、XML 名前空間仕様によって XML ドキュメント内の要素名と属性名を一意にすることができます。XML 名前空間を使用すると、XML ドキュメントに複数の XML ボキャブラリの要素名または属性名を含めることができます。
PHP の
名前空間はPHPバージョン 5.3 以降に導入されました。クラス、関数、変数の名前の衝突を回避できます。PHPでは、名前空間は名前空間ブロックで定義されます。
# ファイル phpstar/foobar.php
名前空間 phpstar ;
クラス FooBar
{
public function foo () : void
{
echo 'Hello world, from function foo' ;
}
public function bar () : void
{
echo 'Hello world, from function bar' ;
}
}
PHP 名前空間は、次のさまざまな方法で参照できます。
# ファイル index.php
# ファイルをインクルードします
include "phpstar/foobar.php" ;
# オプション 1: クラス名の前に名前空間を直接付ける
$obj_foobar = new \phpstar\FooBar ();
# オプション 2: 名前空間をインポートする
use phpstar\FooBar ;
$obj_foobar = new FooBar ();
# オプション 2a: 名前空間をインポートしてエイリアスする
use phpstar\FooBar as FB ;
$obj_foobar = new FB ();
# 通常の方法でプロパティとメソッドにアクセスします
$obj_foobar -> foo ();
$obj_foobar -> bar ();
名前空間のエミュレーション
名前空間の言語サポートがないプログラミング言語では、識別子命名規則を使用することで、ある程度名前空間をエミュレートできます。たとえば、libpngなどのCライブラリでは、公開されたインターフェースの一部であるすべての関数と変数に固定のプレフィックスが使用されることがよくあります。libpng は次のような識別子を公開します。
png_create_write_struct png_get_signature png_read_row png_set_無効
この命名規則により、識別子が一意であることが合理的に保証され、名前の衝突なしに大規模なプログラムで使用できます。[15]同様に、もともとFortranで書かれた多くのパッケージ(BLAS、LAPACKなど)は、関数名の最初の数文字を予約して、関数がどのグループに属しているかを示します。
この手法にはいくつかの欠点があります。
- ネストされた名前空間にはうまく対応できません。識別子の使用はすべて完全な名前空間修飾を必要とするため、識別子が過度に長くなります。
- 個人または組織が一貫性のない命名規則を使用することがあり、望ましくない難読化が生じる可能性があります。
- 識別子のグループに対する複合操作または「クエリベース」操作は、それらが宣言されている名前空間に基づいて、扱いにくくなったり実行不可能になったりします。
- 識別子の長さが制限されている言語では、プレフィックスを使用すると、関数の動作を識別するために使用できる文字数が制限されます。これは、識別子ごとに 6 文字しか提供されなかったFORTRAN 77で最初に記述されたパッケージで特に問題になります。たとえば、BLAS関数
DGEMMfunction の名前は、倍精度数 ("D") と一般行列 ("GE") で動作することを示しており、最後の 2 文字だけが、実際に何を行うか、つまり行列間の乗算 ("MM") を示しています。
いくつかの利点があります:
- ソースコード ファイル内の名前を見つけるのに特別なソフトウェア ツールは必要ありません。grep のような単純なプログラムで十分です。
- 名前空間名の競合はありません。
- 名前を変更する必要がないため、潜在的な非互換性の問題は発生しません。
参照
- 11桁の配達先 郵便番号
- 二名法(生物学における属-種)
- 化学命名法
- デューイ十進分類法
- デジタルオブジェクト識別子
- ドメインネームシステム
- 第四の壁
- アイデンティティ(オブジェクト指向プログラミング)
- 米国議会図書館分類
- 星表と天文学上の命名規則
- 抽象化レベルの違反
- XML名前空間
- 引数依存の名前検索
参考文献
- ^ Adya, Atul; Bolosky, William; Castro, Miguel; Cermak, Gerald; Chaiken, Ronnie; Douceur, John; Howell, Jon; Lorch, Jacob; Theimer, Marvin; Wattenhofer, Roger (2002). FARSITE: Federated, Available, and Reliable Storage for an Incompletely Trusted Environment (PDF) . Proc. USENIX Symp. on Operating Systems Design and Implementation. オリジナル(PDF)から2010-07-28 にアーカイブ。
ファイル システムによって確立される主要な構成要素は、ファイルの論理リポジトリである階層型ディレクトリ名前空間です。
- ^ 「C# FAQ: 名前空間とは」。C# Online Net。2013 年 10 月 20 日にオリジナルからアーカイブ。2010年 2 月 23 日に取得。
名前空間とは、アセンブリ、クラス、または型のグループに他なりません。名前空間は、通常機能に基づいてグループに編成されたクラスのコンテナー (ディスク フォルダーのような) として機能します。C# の名前空間
構文
では、名前空間を入れ子にすることができます。
- ^ 「PHP の名前空間の概要」。PHP マニュアル。
名前空間とは何ですか? 最も広い定義では、名前空間はアイテムをカプセル化する方法です。これは多くの場所で抽象的な概念として見ることができます。たとえば、どのオペレーティング システムでも、ディレクトリは関連するファイルをグループ化する役割を果たし、ディレクトリ内のファイルの名前空間として機能します。
- ^ 「パッケージの作成と使用」。Javaドキュメント。Oracle。
パッケージは、アクセス保護と名前空間管理を提供する関連型のグループです。型とは
、
クラス、
インターフェース
、
列挙型
、注釈型を指すことに注意してください。列挙型と注釈型は、それぞれクラスとインターフェースの特殊な種類であるため、このレッスンでは、型を単にクラスとインターフェースと呼ぶことがよくあります。
[より良い情報源が必要]
- ^ XML Core Working Group (2009 年 12 月 8 日). 「XML 1.0 の名前空間 (第 3 版)」. W3C . 2012 年 3 月 30 日閲覧。
- ^ Moats, Ryan (1997 年 5 月). 「構文」. URN 構文. IETF . p. 1. sec. 2. doi : 10.17487/RFC2141 . RFC 2141. 2012 年 3 月 30 日閲覧。
- ^ Stephen J. Gowdy. 「USB ID のリスト」 2013 年。
- ^ Sollins & Masinter (1994 年 12 月)。「機能要件」。Uniform Resource Names の機能要件。IETF。p . 3. sec. 2. doi : 10.17487/RFC1731。RFC 1731。2012年3 月 30日閲覧。
- ^ 「C# FAQ: 名前空間とは」。C # Online Net。2013 年 10 月 20 日時点のオリジナルからアーカイブ。2010 年 2 月 23 日取得。
たとえば、[
Windows
の場合] 組み込みの入出力 (I/O) クラスとメンバーにアクセスするには、System.IO 名前空間を使用します。または、Web 関連のクラスとメンバーにアクセスするには、System.Web 名前空間を使用します。
- ^ 「名前空間とは、プログラム内で使用される名前の論理的なグループです。」 Webopedia.com。2002 年 4 月 10 日。2011年 7 月 26 日閲覧。
- ^ 「名前空間を使用すると、クラス、オブジェクト、関数などのエンティティを名前でグループ化できます」。Cplusplus.com 。 2011年7月26日閲覧。
- ^ 「6. モジュール」。Pythonチュートリアル。Python Software Foundation。2010年10 月 25 日閲覧。
- ^ 「Python スコープと名前空間」。Docs.python.org。2011年 7 月 26 日閲覧。
- ^ https://docs.python.org/3/tutorial/modules.html 「一般的に、モジュールまたはパッケージから * をインポートする習慣は好ましくありません」
- ^ Danny Kalev. 「なぜ名前空間が嫌いなのか」。2016年7月9日時点のオリジナルよりアーカイブ。
{{cite web}}: CS1 maint: bot: original URL status unknown (link)
