はじめに
PHPでクイズを作りたいと思い、間違いやすそうな部分を問題にしました。
PHPのアクセス修飾子
// PHPのバージョンは8.0.3とする
class Super {
// public、protected、privateそれぞれのパターン
アクセス修飾子 $name;
public function __construct(string $name)
{
$this->setName($name);
}
public function setName(string $name): void
{
$this->name = $name;
}
public function getName(): string
{
return $this->name;
}
}
class Sub extends Super {
public function __construct(string $name)
{
parent::__construct($name);
}
}
$sub = new Sub('佐藤さん');
$sub->name = '鈴木さん';
$sub->setName('高橋さん');
// 出力結果
echo $sub->getName();
問題
Superクラスの$nameがpublic、protected、privateのそれぞれのケースでの出力結果を下記の選択肢から選んでください。
1.エラーが表示される
2.佐藤さんが表示される
3.鈴木さんが表示される
4.高橋さんが表示される
解答
publicの場合
表示
4.高橋さんが表示される
解説
最後の$sub->setName('高橋さん')
で
Superクラスの$name
へセットされて表示される。
protectedの場合
表示
1.エラーが表示される
解説
エラー内容は
Fatal error: Uncaught Error: Cannot access protected property Sub::$name
原因は下記のコードでprotected
は自身のクラスと自身のクラスを継承したクラスと
親クラスからのみでしかアクセスできないため、エラーとなる。
privateの場合
表示
3.鈴木さんが表示される
解説
結果から$name
はSuperクラスとSubクラスの両方で所持されている。
Subクラスの$name
は、最初は定義されていないが、
PHPは未定義のプロパティに対して動的に生成するため、
$user->name = '鈴木さん'
この段階でSubクラスに存在する。
Superクラスの$name
は、
$sub = new Sub('佐藤さん')
、$sub->setName('高橋さん')
の2回セットされており
最後にセットされた高橋さんが値がセットされている。
出力するときはSubクラスで生成されたpublic $name
にアクセスされる。
※なお、動的プロパティはPHP 8.2では非推奨になり、PHP9.0ではエラーとなる模様。
https://wiki.php.net/rfc/deprecate_dynamic_properties