# $Id: README.namespaces.ja 372 2008-01-01 00:06:30Z m-takagi $ # EN-Revision: 1.7 # (http://cvs.php.net/viewcvs.cgi/php-src/README.namespaces?revision=1.7&view=markup) 設計 ==== 名前空間によって解決しようとしているのは、PHP のライブラリのクラス名が あまりにも長ったらしくなってしまっているという問題です。autoloader に 取って代わるつもりはありませんし、パッケージモデルを念頭においているもの でもありません。単に名前の管理を行うためだけのものです。 名前空間の定義は、次のように行います。 Zend/DB/Connection.php: 名前空間の定義は、以下のようなものです。 その中にあるクラス名や関数名の先頭には、名前空間が自動的に付加されます。 名前空間内では、ローカルな名前のほうがグローバルな名前よりも常に優先され ます。同じ名前空間を複数の PHP ファイルで使用することができます。名前空 間の宣言は、ファイルの先頭で行う必要があります。 名前空間内のクラスや関数を使用する際には、常にフルネームで指定する必要が あります。つまり、Zend::DB::Connection とか Zend::DB::connect といったよ うになります。 名前空間やクラス名をインポートすることができます。 use 文は、単に名前のエイリアスを定義するだけです。これにより、名前空 間やクラスの別名を作成します。"use A::B::C::D;" は "use A::B::C::D as D;" と同じ意味となります。imoprt 文は、グローバル スコープ (関数やクラスの外部) ならいつでも使用可能で、定義した場所からそ のファイルの最後まで有効となります。しかし、use 文はファイルの先頭に 書いておくことをお勧めします。use 文は、それを書いたファイル内でのみ 有効です。 "空の" 名前空間 (接頭辞 ::) は、グローバル名前空間を明示的に指定する際に 便利です。クラス名や関数名の先頭に :: をつけると、それはグローバルスコー プとして解釈されます。 定数 __NAMESPACE__ には、現在の名前空間が格納されます。これを使用して、 完全修飾名をコールバック関数として渡すことができます。 グローバル名前空間では、定数 __NAMESPACE__ の値は空文字列となります。 名前空間内での名前解決は、次の順で行われます。 1) すべての修飾名が、コンパイル時にインポート方式の指定にあわせて変換さ れます。たとえば、"use A::B::C" を指定した環境で "C::D::e()" を使用した 場合、それが "A::B::C::D::e()" に変換されます。 2) 修飾されていないクラス名が、コンパイル時にインポート方式の指定にあわ せて変換されます。たとえば、"use A::B::C" を指定した環境で "new C()" を 使用した場合、それが "new A::B::C()" に変換されます。 3) 名前空間の中で、修飾されていない関数コールのうち、現在の名前空間で定 義されているもの (そしてその関数コールをパースする時点で既知のもの) につ いては、現在の名前空間の関数に変換されます。 4) 名前空間の中で、修飾されていない関数コールのうち、現在の名前空間では 定義されていないものについては実行時に解決されます。関数 foo() が名前空 間 A::B でコールされた場合、まず最初に現在の名前空間から namespace A::B::foo() を探してコールしようとします。もし見つからなかった場合は、内 部関数 foo() をコールしようとします。foo() を名前空間内で使用した場合に は、(もし同名の関数がその名前空間になければ) PHP の内部関数しかコールで きないことに注意しましょう。::foo() を使用すれば、グローバル名前空間内の 任意の関数をコールできます。 5) 修飾されていないクラス名を、実行時に解決します。たとえば "new Exception()" は、まず現在の名前空間にあるクラスを使用 (そして __autoload()) しようとします。それに失敗すると、PHP の内部クラスを使用し ます。名前空間内で "new A" を使用すると、同一名前空間内のクラスか PHP の内部クラスしか作成できないことに注意しましょう。しかし "new ::A" を使 用すれば、グローバル名前空間内の任意のクラスを作成することができます。 6) 修飾されている関数名を実行時に解決します。たとえば A::B::foo() はまず 名前空間 A::B の関数 foo() のコールを試み、それに失敗すると、クラス A::B (必要に応じて __autoload() します) のスタティックメソッド foo() をコール します。 7) 修飾されているクラス名を、その名前空間のクラスとして解決します。つま り、"new A::B::C()" は名前空間 A::B のクラス C を作成します。 サンプル -------- もしクラス名と名前空間名が衝突したら? TODO ==== * 名前空間定数のサポート? * パフォーマンスの問題 - 名前空間内で内部関数をコールしたときのパフォーマンスが低下する。とい うのも、PHP はまず現在の名前空間の中でその名前の関数を探そうとするか ら。 - スタティックメソッドのコールしたときのパフォーマンスが低下する。とい うのも、PHP はまず名前空間の中でその関数を探そうとするから。 * リフレクション API の拡張? * ReflectionPackage クラスの追加 + getName() + getClasses() + getFunctions() + getFiles() * ReflectionClass および ReflectionFunction に getNamespace() メソッドを追加 *「名前空間(namespace)」じゃなくて「パッケージ(package)」という名前に変更する?