
PHP8 上級/準上級試験の認定模擬問題として、プライム・ストラテジー様のPRIME STUDYが認定されているようです。ただ、この模擬問題には解説がありませんので解説をまとめていこうと思います。シリーズ第7回目です。

PHP初級レベルから脱却して中級/上級レベルにいきたい人にピッタリの内容ですね。
PRIME STUDY認定模擬問題のリンクはこちらです → https://study.prime-strategy.co.jp/
問題文
名前空間に関する説明の中で、誤っているものを1つ選びなさい。
なお「\」はバックスラッシュに読み替えること。
また、すべてのコードには下記のコードが適切な箇所に書かれているものとする。
declare(strict_types=1);
error_reporting(-1);
(1)
名前空間は、namespace キーワードを使って宣言する。
名前空間の宣言は、通常他のコードより前にファイルの先頭で宣言をする必要がある。名前空間の宣言前に書かれたクラスなどは、宣言された名前空間には含まれない。
そのため、以下のコード
class Hoge {
}
namespace Name;
class Foo {
}
$obj = new Hoge();
var_dump($obj);
を実行すると、結果は次のとおりとなる。
Fatal error: Uncaught Error: Class 'Name\Hoge' not found in …
これはHogeがグローバル空間で宣言をされているためなので、以下のコード
class Hoge {
}
namespace Name;
class Foo {
}
$obj = new \Hoge();
var_dump($obj);
は正しく実行でき、結果は次のとおりとなる。
object(Hoge)#1 (0) {
}
(2)
名前空間は、namespace キーワードを使って宣言する。
また、名前空間はディレクトリやファイルと同様に、名前空間の階層構造を指定することができる。
そのため、以下のコード
namespace Name\SubName;
class Hoge {
}
$obj = new Hoge();
var_dump($obj);
を実行すると、結果は次のとおりとなる。
object(Name\SubName\Hoge)#1 (0) {
}
(3)
名前空間の定義がない場合、すべてのクラスや関数の定義はグローバル空間に配置される。PHP で定義済みのクラスも、グローバル空間に配置される。
先頭に \ (バックスラッシュ) を付けると、名前空間の内部からであってもグローバル空間の名前を指定することができる。
そのため、以下のコード
namespace Name;
try {
throw new Exception('error');
} catch (Exception $e) {
echo 'in to catch';
}
を実行すると、結果は次のとおりとなる。
Fatal error: Uncaught Error: Class 'Name\Exception' not found in …
一方で以下のコード
namespace Name;
try {
throw new \Exception('error');
} catch (\Exception $e) {
echo 'in to catch';
}
を実行すると
in to catch
となる。
(4)
PHP でのエイリアス作成には use 演算子を使用する。
use で指定する名前空間付きの名前の、先頭の \ (バックスラッシュ) は不要で、推奨されない。
そのため、以下のコード
namespace Name;
class Hoge {
}
class Foo {
}
namespace Name\Sub;
// よく使われているuse
use Name\Hoge;
$obj = new Hoge();
var_dump(NAMESPACE, $obj);
namespace Name\Sub2;
// エイリアスを切ったuse
use \name\Hoge as Bar; // 先頭の \ は推奨されていない
echo PHP_EOL;
$obj = new Bar();
var_dump(NAMESPACE, $obj);
namespace Name\Sub3;
// useのグループ化
use Name{Hoge, Foo};
echo PHP_EOL;
$hoge_obj = new Hoge();
$foo_obj = new Foo();
var_dump(NAMESPACE, $hoge_obj, $foo_obj);
は正しく実行でき、結果は次のとおりとなる。
string(8) "Name\Sub"
object(Name\Hoge)#1 (0) {
}
string(9) "Name\Sub2"
object(Name\Hoge)#2 (0) {
}
string(9) "Name\Sub3"
object(Name\Hoge)#1 (0) {
}
object(Name\Foo)#2 (0) {
}
解説
選択肢1
誤っています。
PHPの名前空間(Namespace)は、クラスや関数、定数などの「名前の衝突」を防ぐための仕組みです。例えば、異なるファイルで同じクラス名を使いたい場合、名前空間を使うことで区別できます。
namespace を使う場合、コードの最初に namespace を書かなければいけません。PHPでは namespace より前にクラスなどのコードを書くとエラーになります。
選択肢2
正しいです。
PHPの名前空間(Namespace)は、クラスや関数、定数の名前の衝突を防ぐための仕組みです。
名前空間には階層構造を持たせることもできるため、大規模なプロジェクトでも整理しやすくなります。
名前空間には階層構造を持たせたい場合、1行目のように「namespace Name\SubName;」のように書きます。現在の名前空間内では、クラス名だけで使えます。そのため6行目「new Hoge();」は 「Name\SubName\Hoge」を指します。他の名前空間から使いたい場合は、「new \Name\SubName\Hoge();」のようにフルネームで指定する必要があります。
ただし、他の名前空間から使いたい場合もuseを使って「use Name\SubName\Hoge;」と書くことで フルネーム指定せず、「new Hoge();」と書けるようになります。
選択肢3
正しいです。
名前空間の内部では、グローバル空間のクラスや関数を使用する際に \ を先頭に付ける必要があります。このルールを守らない場合、現在の名前空間でそのクラスが定義されていない限り、エラーになります。
選択肢4
正しいです。
use 演算子はエイリアスの作成に使用されます。また、名前空間付きの名前の先頭に \ を付けることは有効ですが、推奨されません。加えて、PHP 7.0以降では use 演算子を使った名前空間のグループ化が可能です。
正解選択肢
以上より選択肢1が正解となります。
コメント