コンピュータにおいて、名前空間とは、様々な種類のオブジェクトを識別し参照するために使用される記号(名前)の集合です。名前空間によって、特定のオブジェクト群すべてが一意の名前を持つことが保証され、容易に識別できるようになります。
名前空間は、異なるコンテキストで名前を再利用できるように、一般的に階層構造になっています。例として、各人が名字と、親族と共有する姓を持つ命名システムを考えてみましょう。家族のメンバーの名字が各家族内でのみ一意である場合、各人は名字と姓の組み合わせによって一意に識別できます。ジェーン・ドウは一人しかいませんが、ジェーンは複数存在する可能性があります。ドウ家の名前空間内では、「ジェーン」だけでこの人物を明確に指定できますが、すべての人の「グローバル」名前空間内では、フルネームを使用する必要があります。
名前空間の代表的な例としては、ファイルに名前を割り当てるファイルシステムが挙げられます。 [ 1 ] 一部のプログラミング言語では、変数やサブルーチンを名前空間に整理しています。[ 2 ] [ 3 ] [ 4 ]コンピュータネットワークや分散システムでは、コンピュータ、プリンタ、Webサイト、リモートファイルなどのリソースに名前を割り当てます。オペレーティングシステムは、カーネルリソースを分離された名前空間で分割して、 OSレベルの仮想化コンテナをサポートできます。
同様に、階層型ファイルシステムでは、ファイルをディレクトリに整理します。各ディレクトリは独立した名前空間であるため、「letters」ディレクトリと「invoices」ディレクトリの両方に「to_jane」というファイルが含まれる可能性があります。
コンピュータプログラミングにおいて、名前空間は通常、特定のタスクに関連するシンボルや識別子をグループ化し、同じ名前を持つ複数の識別子間の名前の衝突を回避するために使用されます。
コンピュータネットワークにおいて、ドメインネームシステム(DNS)はウェブサイト(およびその他のリソース)を階層的な名前空間に整理します。
要素名は開発者によって定義されます。そのため、異なるXMLアプリケーションで作成されたXMLドキュメントを混在させようとすると、しばしば競合が発生します。
このXMLにはHTMLテーブル情報が含まれています。
<table> <tr> <td>良い</td> <td>悪い</td> </tr> </table>このXMLには、テーブル(つまり家具)に関する情報が含まれています。
<table> <name>マホガニーコーヒーテーブル</name> <width> 30 </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> 30 </f:width> <f:length> 120 </f:length> </f:table>名前空間内の名前は、名前空間名とローカル名で構成されます。[ 5 ] [ 6 ]名前空間名は通常、ローカル名の接頭辞として適用されます。
拡張バッカス・ナウア記法では:
名前= <名前空間名>セパレータ<ローカル名> ローカル名が単独で使用される場合、名前解決を使用して、特定のローカル名がどの特定の名前(もしあれば)を指しているかを判断します。
当事者間の責任の委任は、ワールドワイドウェブの構造など、現実世界のアプリケーションにおいて重要です。名前空間を使用すると、グローバルな一意性を維持しながら、識別子の割り当てを複数の名前発行組織に委任できます。[ 8 ]中央登録機関は、割り当てられた名前空間名を登録します。各名前空間名は、割り当てられた名前空間内の名前の割り当てを担当する組織に割り当てられます。この組織は、名前を自身で割り当てる名前発行組織である場合もあれば、名前空間の一部を別の組織にさらに委任する別の登録機関である場合もあります。
名前空間を第三者に委任できる命名規則は、階層型名前空間と呼ばれます。
階層構造は、各サブ委譲における名前空間名の構文が同じである場合に再帰的である。再帰的階層構造の例としては、ドメインネームシステム( DNS)が挙げられる。
非再帰的な階層構造の例としては、インターネット割り当て番号機関(IANA)番号を表す統一リソース名(URI)が挙げられる。
名前空間名は、名前にコンテキスト(コンピュータサイエンスではスコープ)を与えることがあり、これらの用語は時として同義語として使われる。しかし、名前のコンテキストは、名前が出現する場所や名前の構文など、他の要因によっても与えられる場合がある。
多くのプログラミング言語では、名前空間は識別子のコンテキストです。オペレーティングシステムでは、ディレクトリが名前空間の一例です。ディレクトリ内の各名前は、1つのファイルまたはサブディレクトリを一意に識別します。[ 9 ]
原則として、名前空間内の名前は複数の意味を持つことはできません。つまり、同じ名前空間内で異なる意味を持つ名前は存在しません。名前空間はコンテキストとも呼ばれます。なぜなら、異なる名前空間では同じ名前でも異なる意味を持つことができ、それぞれの意味はその名前空間にふさわしいものだからです。
名前空間のその他の特徴は以下のとおりです。
上記で説明したような抽象言語としての技術的な使用法に加えて、一部の言語には、明示的な名前空間制御などに使用される特定のキーワードがあります。以下は、C++ における名前空間の例です。
import std ;// これは、名前を現在のスコープに取り込む方法です。この場合、グローバルスコープに取り込んでいます。using std :: println ;namespace box1 { constexpr int BOX_SIDE = 4 ; }namespace box2 { constexpr int BOX_SIDE = 12 ; }int main () { constexpr int BOX_SIDE = 42 ; println ( "{}" , box1 :: BOX_SIDE ); // 出力は 4. println ( "{}" , box2 :: BOX_SIDE ); // 出力は 12. println ( "{}" , BOX_SIDE ); // 出力は 42. }コンピュータサイエンスにおける名前空間(名前スコープとも呼ばれる)は、一意の識別子またはシンボル(つまり名前)の論理的なグループを保持するために作成された抽象的なコンテナまたは環境です。名前空間で定義された識別子は、その名前空間のみに関連付けられます。同じ識別子は、複数の名前空間で独立して定義できます。つまり、ある名前空間で定義された識別子は、別の名前空間で定義された同じ識別子と同じ意味を持つ場合もあれば、持たない場合もあります。名前空間をサポートする言語は、識別子(その定義ではなく)がどの名前空間に属するかを決定する規則を指定します。[ 10 ]
この概念は、たとえ話で説明できます。X社とY社という2つの会社が、それぞれ従業員にID番号を割り当てていると想像してください。X社には同じID番号を持つ従業員が2人いてはならず、Y社も同様です。しかし、両社で同じID番号が使われていても問題ありません。例えば、ビルがX社に、ジェーンがY社に勤務している場合、2人とも従業員番号123番であっても問題ありません。このたとえ話では、ID番号は識別子であり、会社は名前空間の役割を果たします。同じ識別子がそれぞれの名前空間で異なる人物を識別しても、問題は生じません。
大規模なコンピュータプログラムやドキュメントでは、数百、数千もの識別子が存在するのが一般的です。名前空間(または同様の手法。名前空間のエミュレーションを参照)は、ローカル識別子を隠蔽するメカニズムを提供します。名前空間は、論理的に関連する識別子を対応する名前空間にグループ化する手段を提供し、システムのモジュール性を高めます。
データストレージデバイスと多くの最新のプログラミング言語は名前空間をサポートしています。ストレージデバイスはディレクトリ(またはフォルダ)を名前空間として使用します。これにより、異なるディレクトリに保存されている限り、同じ名前の2つのファイルをデバイスに保存できます。一部のプログラミング言語(C++、Pythonなど)では、名前空間の名前付け識別子自体が、囲んでいる名前空間に関連付けられています。したがって、これらの言語では名前空間をネストして名前空間ツリーを形成できます。このツリーのルートには、名前のないグローバル名前空間があります。
C言語では、正式な名前空間は存在しませんが(ただし、名前空間は頻繁に模倣されます)、識別子は異なる名前空間に属すると考えることができます。つまり、通常の識別子、タグ(struct/ union/ enum)、メンバ名、ラベルです。たとえば、名前はFoo次の4つのコンテキストで再利用できます。
#include <stdio.h>// タグ名前空間内struct Foo { int Foo ; // メンバー名前空間内};// 関数名とパラメータ(通常の識別子)struct Foo Foo ( int Foo ) { struct Foo result = { . Foo = Foo }; if ( Foo < 0 ) { goto Foo ; // ラベル名前空間内}return result ; Foo : result.Foo = 0 ; return result ; }int main ( ) { // 関数 Foo () を使用して、Foo という名前の構造体 Foo を作成します。 struct Foo Foo = Foo ( 42 ); printf ( "%d \n " , Foo.Foo ) ; }さらに、 C99以降、C言語では匿名構造体を名前空間として使用することが可能です。
Math.h :
#pragma onceconst struct { double PI ; double ( * sin )( double ); } Math ;Math.c :
#include <math.h>static double _sin ( double arg ) { return sin ( arg ); }const struct { double PI ; double ( * sin )( double ); } Math = { M_PI , _sin };Main.c :
#include <stdio.h> #include "Math.h"int main ( ) { printf ( "sin(0) = %d \ n " , Math.sin ( 0 ) ); printf ( "pi is %f \n " , Math.PI ) ; }C++では、名前空間は名前空間ブロックで定義されます。[ 11 ]
namespace abc { int bar ; }このブロック内では、識別子は宣言どおりに使用できます。このブロック外では、名前空間指定子をプレフィックスとして付ける必要があります。たとえば、 の外では、にアクセスするには と記述する必要があります。C++ には、この冗長性を不要にする別の構文があります。次の行を追加することでnamespaceabcbarabc::bar
名前空間abcを使用する;コードの一部に対して、プレフィックスはabc::もはや必要ありません。
名前空間内で明示的に宣言されていない識別子は、グローバル名前空間に属するものとみなされます。
int foo ;これらの識別子は宣言どおりにそのまま使用することも、グローバル名前空間は無名であるため、名前空間指定子を::接頭辞として付けることもできます。たとえば、fooは とも記述できます::foo。
C++ における名前空間解決は階層的です。つまり、仮想的な名前空間 内ではfood::soup、識別子 はChickenを参照しますfood::soup::Chicken。food::soup::Chickenが存在しない場合は、 を参照しますfood::Chicken。 も も存在しfood::soup::Chickenない場合は、 はグローバル名前空間の識別子 を参照します。food::ChickenChicken::Chicken
C++ の名前空間は、名前の衝突を回避するために最もよく使用されます。最近の C++ コードでは名前空間が広く使用されていますが、古いコードのほとんどはこの機能を使用していません。これは、言語の初期バージョンには名前空間が存在しなかったためです。たとえば、C++ 標準ライブラリ全体は内に定義されていますが、標準化される前は、多くのコンポーネントが元々グローバル名前空間にありました。ステートメントを使用すると、シンボルを現在のスコープにインポートできます。namespacestdusing
using後方互換性以外の理由 (利便性など) でヘッダー内のステートメントを使用することは、そのusingステートメントがヘッダーを含むすべての翻訳単位に伝播するため、良いコーディング慣行に反すると考えられています。ただし、モジュールはusing明示的にマークされていない限りステートメントをエクスポートしないためexport、ステートメントの使用はより安全になります。たとえば、一致する名前空間を持つusingモジュールをインポートし、その名前空間のシンボルに対してステートメントを使用して冗長な名前空間を簡略化できます。Java や Rust などの他の言語とは異なり、C++ のモジュール、名前空間、ソース ファイル構造は必ずしも一致するとは限りませんが、明確さのために一致させるのが慣例です (たとえば、モジュールは名前空間付きクラスと一致し、ファイルfoo/bar/baz/Qux.cppmに存在します)。wikipedia.project.utilwikipedia::project::utilusingfoo.bar.baz.Quxfoo::bar::baz::Qux
usingモジュール型翻訳単位を使用する場合、冗長なネストされた名前空間を簡略化するために使用する必要があります。
export module wikipedia . project . App ;import std ;import wikipedia.project.fs ; import wikipedia.project.util ;using wikipedia :: project :: fs :: File ; using wikipedia :: project :: util :: ConfigLoader ; using wikipedia :: project :: util :: logging :: Logger ; using wikipedia :: project :: util :: logging :: LoggerFactory ;export namespace wikipedia :: project {class App { private : Logger logger ; // プライベートなフィールドとメソッドpublic : App () : logger { LoggerFactory :: getLogger ( "Main" )} { ConfigLoader cl ( File ( "config/config_file.txt" )); logger . log ( "アプリケーション起動中..." ); // 残りのコード} };}C++11ではインライン名前空間が導入されました。これは、そのメンバーが囲んでいる名前空間のメンバーでもあるかのように扱われるものです。インライン名前空間は、`<inline namespace>`と記述することで宣言されます。これは暗黙のステートメントに似ており、修飾シンボルは省略可能です。inlinenamespaceusingnamespace
inline プロパティは推移的です。名前空間がaインライン名前空間を含みb、さらにそのインライン名前空間が別のインライン名前空間を含む場合c、のメンバーは、またはcのメンバーであるかのようにアクセスできます。ab
インライン名前空間の主な用途は、ABI互換性とバージョン管理です。ライブラリ開発者は、APIの異なるバージョンをそれぞれ別のインライン名前空間(例:v1、v2)に配置し、現在必要なバージョンをインライン化することで、ABI互換性を管理できます。新しいバージョンがリリースされたら、inlineキーワードを新しいバージョンの名前空間に移動することで、ユーザーは新しいバージョンに自動的にリンクできると同時に、明示的な修飾子によって古いバージョンにもアクセスできるようになります。
namespace mylib :: utils { namespace v1 { [[ deprecated ( "代わりに mylib::utils::v2::func() を使用してください" )]] void func () { // 古い実装} }// v2 は現在アクティブなバージョンですinline namespace v2 { void func () { // 新しい実装} } }int main () { // mylib::utils::v2::func() を暗黙的に呼び出しますmylib :: utils :: func ();// mylib::utils::v2::func() を明示的に呼び出しますmylib :: utils :: v2 :: func ();// mylib::utils::v1::func() を明示的に呼び出しますmylib :: utils :: v1 :: func ();return 0 ; }C# 言語では名前空間が多用されます。すべての.NET Framework クラスは、より明確に使用し、混乱を避けるために名前空間に整理されています。また、プログラマーは作業を整理し、名前の衝突を避けるためにカスタム名前空間を広く使用しています。クラスを参照する場合、名前空間の後にクラス名を付ける完全修飾名を指定できます。
System.Console.WriteLine ( " Hello World ! " ) ; int i = System.Convert.ToInt32 ( " 123 " ) ;または、usingステートメントを追加します。これにより、その名前空間内のすべてのクラスの完全な名前を記述する必要がなくなります。
Systemを使用します。Console.WriteLine ( "Hello World!" ) ; int i = Convert.ToInt32 ( " 123 " ) ;上記の例では、Systemは名前空間であり、ConsoleおよびはConvert内で定義されたクラスですSystem。
![]()
C++とは異なり、名前空間内のすべてのシンボルのみをインポートできます( C++、Rust、Javaとusing同様)。Javaのように個々のシンボルやクラスをインポートすることはできません。usingnamespaceuse*import*
名前空間Wikipedia.Project ;using System ; using System.IO ;Microsoft.Extensions.Loggingを使用します。Wikipedia.Project.Utilityを使用します。class App { private static ILogger < Program > logger ;public App () { ConfigLoader cl = new ConfigLoader ( Path . Combine ( "config" , "config_file.txt" )); LoggerFactory loggerFactory = LoggerFactory . Create ( builder => { builder . AddConsole (); }); logger = loggerFactory . CreateLogger < Program > (); logger . LogInformation ( "アプリケーション起動中..." ); // 残りのコード} }C++とは異なり、C#の名前空間ではシンボルの相対参照は許可されていません。たとえば、クラスを名前空間内から参照する場合でも、Foo.Bar.Baz.Quxとして参照することはできません。クラスを参照するには、名前空間をインポートするか、完全修飾名を使用する必要があります。Baz.QuxFoo.BarFoo.Bar.BazQuxFoo.Bar.Baz.Qux
Javaでは、名前空間の概念はJava パッケージに具現化されています。すべてのコードはパッケージに属しますが、そのパッケージに明示的に名前を付ける必要はありません。他のパッケージのコードにアクセスするには、適切な識別子の前にパッケージ名をプレフィックスとして付けます。たとえば、パッケージ内のコードは として参照できます(これは完全修飾クラス名として知られています)。C++ と同様に、Java にはパッケージ名を入力する必要がない構文 ( ) があります。ただし、特定の機能 (リフレクションなど) では、プログラマーは完全修飾名を使用する必要があります。classStringjava.langjava.lang.Stringimport
C++とは異なり、Javaの名前空間は言語の構文に関して階層構造になっていません。しかし、パッケージ名は階層構造になっています。例えば、で始まるすべてのパッケージはJavaプラットフォームjavaの一部であり、パッケージには言語の中核となるクラスが含まれ、パッケージにはリフレクションに特に関連する中核クラスが含まれています。java.langjava.lang.reflect
Java(およびAda、C#など)では、名前空間/パッケージはコードの意味カテゴリを表します。たとえば、C#では、システム(.NETフレームワーク)によって提供されるコードが含まれます。これらのカテゴリの具体性や階層の深さは、言語によって異なります。namespaceSystem
関数スコープとクラススコープは、可視性、アクセス可能性、およびオブジェクトのライフタイムと密接に結びついた暗黙の名前空間と見なすことができます。
Java では、パッケージを C++ のように部分的に修飾することはできません。たとえば、名前空間をインポートしてから として参照することはできません。javaシンボルは、完全修飾するか、スコープに完全にインポートする必要があります。ステートメントは推移的ではなく、C++ のように意図的にマークすることもできません。すべてのステートメントはファイルの先頭に記述する必要があり、他のスコープで記述することはできません。これは、C++ ではと記述することで名前空間をインポートし、として参照できるのとは対照的です。java.util.ArrayListutil.ArrayListimportexportimportstdusingnamespacestd;std::chrono::system_clockchrono::system_clock
パッケージorg.wikipedia.project ;import java.nio.file.Paths ; import java.util.logging.Level ; import java.util.logging.Logger ;import org.wikipdia.project.util.ConfigLoader ;public class App { private static final Logger logger = Logger.getLogger ( Main.class.getName ( ) ) ;public App () { ConfigLoader cl = new ConfigLoader ( Paths.get ( " config / config_file.txt" ) ); logger.log ( Level.INFO , "アプリケーション起動中..." ) ; //残りのコード} }Java はクラス外の独立した関数をサポートしていないため、静的クラスメソッドといわゆる「ユーティリティクラス」(プライベートコンストラクタを持ち、すべてのメソッドとフィールドが静的なクラス)は、C++ スタイルの名前空間に相当します。例としてはjava.lang.Math、定数Math.PIやメソッドなどを含む がありますMath.sin()。
import`glob import` ステートメントを使用すると、パッケージ内のすべてのシンボルをインポートできます。これはワイルドカードインポートと呼ばれ、C++ の `glob import` に似ています。たとえば、`glob import` と記述すると、パッケージ内のすべてのクラスがインポートされます。ただし、これはファイル内でシンボル汚染を引き起こす可能性があります。さらに、同じ名前のクラスを持つパッケージに対して `glob import` ステートメントを使用すると、曖昧さが生じ、コンパイルエラーになります。ただし、`glob import`はデフォルトですべての Java ソースファイルに暗黙的にインポートされます。usingnamespaceimportjava.util.*;java.utiljava.lang.*
import java.sql.* ; // java.sql.Date を含む java.sql のすべてのクラスをインポートしますimport java.util.* ; // java.util.Date を含む java.util のすべてのクラスをインポートしますDate d = new Date (); // あいまいな Date 参照によりコンパイルエラーが発生します//代わりに、完全修飾名を使用する必要があります: java.sql.Date sqlDate = new java.sql.Date ( System.currentTimeMillis ( ) ) ; java.util.Date utilDate = new java.util.Date ( ) ;KotlinのパッケージはJavaのパッケージと非常によく似ていますが、Javaではクラスのようなオブジェクトのみがパッケージ内に直接存在できるのに対し、Kotlinでは変数、クラス、型エイリアスなどのトップレベルのシンボルをパッケージ内に直接存在させることができます。
パッケージorg.wikipedia.examplesimport kotlin.math.PIvar myPi = PIfun circleArea ( radius : Double ): Double { return myPi * radius * radius }しかし、Kotlinではトップレベルの非クラスオブジェクトをパッケージ内に直接配置できますが、これはJava仮想マシン内部では生成されたクラス内に存在するものとして表現され、以下のようなものになります。
パッケージorg.wikipedia.examples ;public final class ExampleKt {private static double myPi = Math.PI ;public static final double getMyPi () { return myPi ; }public static final void setMyPi ( double value ) { myPi = value ; }public static final double circleArea ( double radius ) { return myPi * radius * radius ; } }PHPでは、バージョン 5.3 以降で名前空間が導入されました。クラス、関数、変数の名前の衝突を回避できます。PHP では、名前空間は namespace ブロックで定義されます。
# ファイル phpstar/foobar.php名前空間phpstar ;class 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 ();![]()
Pythonでは、名前空間は個々のモジュールによって定義され、モジュールは階層的なパッケージに含まれることができるため、名前空間も階層的になります。[ 12 ] [ 13 ] 一般的に、モジュールがインポートされると、モジュール内で定義されている名前はそのモジュールの名前空間を介して定義され、呼び出し元のモジュールから完全修飾名を使用してアクセスされます。
# mod_a は func1() と func2() という 2 つの関数と Class1 という 1 つのクラスを定義していると仮定しますimport mod_amod_a.func1 ( ) mod_a.func2 ( ) a : mod_a.Class1 = mod_a.Class1 ( )このステートメントを使用すると、関連する名前を呼び出し元モジュールの名前空間に直接挿入でき、呼び出し元モジュールからは修飾名なしでそれらの名前にアクセスできます。from...import...
# mod_a は func1() と func2() という 2 つの関数と Class1 という 1 つのクラスを定義していると仮定しますfrom mod_a import func1func1 () func2 () # これは未定義の名前として失敗します。完全な名前 mod_a.func2() も同様です。a : Class1 = Class1 () # これは未定義の名前として失敗します。完全な名前 mod_a.Class1() も同様です。これは名前を(修飾子なしで)直接インポートするため、警告なしに既存の名前を上書きする可能性があります。
ステートメントの特別な形式は、指定されたパッケージで定義されているすべての名前を呼び出しモジュールの名前空間に直接インポートするものです。この形式のインポートは言語内でサポートされていますが、呼び出しモジュールの名前空間を汚染し、名前の衝突が発生した場合に既に定義されている名前が上書きされるため、一般的には推奨されません。[ 14 ]ただし、Python で使用すると、ネストされた名前空間などの冗長な名前空間を簡素化できます。from...import*fromimport
from selenium.webdriver import Firefox from selenium.webdriver.common.action_chains import ActionChains from selenium.webdriver.common.by import By from selenium.webdriver.common.keys import Keys from selenium.webdriver.remote.webelement import WebElementif __name__ == "__main__" : driver : Firefox = Firefox () element : WebElement = driver . find_element ( By . ID , "myInputField" ) element . send_keys ( f "Hello World { Keys . ENTER } " ) action : ActionChains = ActionChains ( driver ) action . key_down ( Keys . CONTROL ) . send_keys ( 'a' ) . key_up ( Keys . CONTROL ) . perform ()Pythonでは、呼び出し元のモジュールが使用するエイリアスまたは代替名を提供する方法として、以下の機能もサポートしています。importxasy
import numpy as np from numpy.typing import NDArray , float32a : NDArray [ float32 ] = np 。オレンジ( 1000 )Rustでは、名前空間は「モジュール」と呼ばれ、`module`を使用して宣言されますmod。モジュール内のシンボルはデフォルトではプライベートであり、外部からアクセスすることはできませんpub。ただし、`module`キーワードを使用してシンボルを公開する場合は例外です。モジュール内にはサブモジュールを含めることができ、名前空間をネストできます。
usingC++のキーワードと同様に、Rustにはuseシンボルを現在のスコープにインポートするためのキーワードがあります。
mod my_module { pub trait Greet { fn greet ( & self ); }pub struct Person { pub name : String , }impl Greet for Person { fn greet ( & self ) { println! ( "こんにちは、{}!" , self . name ); } } }fn main () { use my_module ::{ Person , Greet };let person = Person { name : String :: from ( "Alice" ) }; person.greet ( ) ; }と記述すると、コンパイラに対して、またはという名前のファイルを見つけるように指示されます。ステートメント内のは、現在の「クレート」(プロジェクト)のルートを指し、は親モジュールを参照するために使用できます。modutil;util.rsutil/mod.rscrateusesuper
mod util ;use std :: fs :: File ;use crate :: util :: ConfigLoader ; use crate :: util :: logging ::{ Logger , LoggerFactory };pub struct App { config_loader : ConfigLoader ; }impl App { pub fn new () -> Self { config_loader = ConfigLoader :: new ( File :: open ( "config/config_file.txt" )); config_loader . load (); let logger : Logger = LoggerFactory :: get_logger ( "Main" ); logger . log ( "Application starting..." ); // 残りのコード} }useRust のキーワードは、C++ の対応するキーワードよりも汎用性が高いです。単一のシンボルのインポート、シンボルエイリアスとグロブインポートusingに加えて、中括弧を使用して同じ行で複数のシンボルをインポートしたり(中括弧はネスト可能)、個別の名前空間をインポートしたり、これらすべてを単一のステートメントで実行したりできます。以下は、これらすべてを使用した例です。asuse
use std ::{ alloc :: Layout , // std::alloc::Layout をインポートfmt :: * , // std::fmt のすべてのシンボルをインポートfs ::{ File , Metadata }, // std::fs::File と std::fs::Metadata をインポートio ::{ prelude :: * , BufReader , BufWriter } // std::io::prelude::*、std::io::BufReader、および std::io::BufWriter のすべてのシンボルをインポートprocess , // std::process 名前空間をインポート (たとえば、std::process::Command は process::Command と参照できます) time ::{ self , Duration } // std::time 名前空間と std::time::Duration をインポート};use std :: fmt :: Result as FmtResult ; // std::fmt::Result を FmtResult に名前変更しますXMLでは、XML名前空間仕様によって、プログラミング言語における名前空間と同様に、XML文書内の要素名と属性名を一意にすることができます。XML名前空間を使用することで、XML文書には複数のXML語彙に属する要素名や属性名を含めることができます。
SAPシステム(特にABAP環境)では、名前空間を使用して、SAPが提供する標準オブジェクトと顧客またはパートナーの開発物との間で名前の衝突を防ぎます。[ 15 ]
名前空間識別子は「/」で区切られ(例:`/MYNS/`)、SAPの名前空間登録プロセスによって予約されます。予約されると、その名前空間で作成されたオブジェクトは一意に識別され、SAPのアップグレードやインポートによる意図しない上書きから保護されます。[ 16 ]
最新のSAP環境(クラウド上のABAPやHDIコンテナなど)では、開発成果物やバンドルを意味的にグループ化するために名前空間も使用されます。
名前空間を言語的にサポートしていないプログラミング言語では、識別子の命名規則を使用することで、名前空間をある程度エミュレートできます。たとえば、libpngのようなCライブラリは、公開インターフェースの一部であるすべての関数と変数に固定のプレフィックスを使用することがよくあります。libpngは次のような識別子を公開します。
png_create_write_struct png_get_signature png_read_row png_set_invalid
この命名規則により、識別子が一意であることが合理的に保証され、名前の衝突なしに大規模なプログラムで使用できます。[ 17 ]同様に、元々 Fortranで書かれた多くのパッケージ( BLAS、LAPACK など) は、関数の名前の最初の数文字を予約して、その関数が属するグループを示します。
この手法にはいくつかの欠点がある。
DGEMMは、それが倍精度浮動小数点数 ( D) と一般行列 ( GE) に対して動作することを示していますが、実際に何をするか ( ) は最後の 2 文字 ( MM) だけです。つまり、行列の乗算です。また、いくつかの利点もあります。
ファイルシステムによって確立される主要な構成要素は、ファイルの論理リポジトリである階層型ディレクトリ名前空間です。
名前空間とは、アセンブリ、クラス、または型のグループのことです。名前空間は、通常機能に基づいてグループ分けされたクラスのコンテナ(ディスクフォルダのようなもの)として機能します。C# の名前空間
構文で
は、名前空間をネストできます。
名前空間とは?最も広い意味では、名前空間は項目をカプセル化する方法です。これは多くの場所で抽象的な概念として見ることができます。たとえば、どのオペレーティングシステムでも、ディレクトリは関連するファイルをグループ化する役割を果たし、その中のファイルの名前空間として機能します。
パッケージは、アクセス保護と名前空間管理を提供する関連型のグループです。...型とは
、
クラス
、
インターフェース、
列挙型
、および注釈型を指します。列挙型と注釈型は、それぞれクラスとインターフェースの特殊な種類であるため、このレッスンでは型は単にクラスとインターフェースと呼ばれることがよくあります。
たとえば、[
Windows
の場合]、組み込みの入出力 (I/O) クラスとメンバーにアクセスするには、System.IO 名前空間を使用します。または、Web 関連のクラスとメンバーにアクセスするには、System.Web 名前空間を使用します。
SAP標準オブジェクトと顧客固有の開発の間で名前の競合を防ぐために名前空間を使用します。
アプリケーション インターフェイス フレームワークでは、名前空間はオブジェクトと構成の論理構造化に使用されます。
{{cite web}}: CS1 maint: bot: 元の URL の状態が不明です (リンク)