PHP 8.1での読み取り専用プロパティの使用方法
PHP 8.1は、サポートを追加します。
readonlyクラスプロパティに関する修飾子です。このようにタグ付けされたプロパティは、一度だけ設定できます。初期化後に読み取り専用プロパティの値を変更しようとすると、エラーが発生します。
"読み取り専用" は非常に曖昧な用語で、個々のプログラミング言語によって異なる意味を持っています。この文脈では、"読み取り専用" は実際には "変更不可" を意味します。プロパティの値を設定することはできますが、その後は変更できません。
読み取り専用プロパティを書く
追加してください
readonly
プロパティを読み取り専用にする修飾子。これはプロパティのアクセス修飾子とその型ヒントの間に配置する必要があります。
class Demo {
public string $Mutable;
public readonly string $Immutable;
public function __construct(
string $Mutable,
string $Immutable) {
$this -> Mutable = $Mutable;
$this -> Immutable = $Immutable;
}
}
$Mutable
これは通常の公的プロパティです。クラスのメソッド内または外部からいつでもその値を変更できます:
$demo = new Demo("A", "X");
$demo -> Mutable = "B";
$Immutable少し異なります。必要なときにその値を読むことはできますが、修正を試みると失敗します。
Error:
// Throws an Error
$demo -> Immutable = "Y";
その
readonly修飾子は、プロモートされたコンストラクタプロパティでもサポートされています:
class Demo {
public function __construct(
public readonly string $Immutable="foobar"
) {}
}
デフォルト値でプロモーションを使用しているとき、コンストラクタ内でプロパティを手動で設定することができます。それはプロパティインスタンスではなく、デフォルト値を受け取る関数のパラメータです。プロモーションは、前の例で示したのと同じコードにデスザグされます。
注意事項
読み取り専用プロパティは、自由に採用できる簡単な構文の拡張です。後方互換性の問題はなく、その使用は完全に任意です。もし追加し始める場合はいくつかの注意点や制限について認識しておく必要があります。
通常のプロパティとは異なり、読み取り専用プロパティは定義にデフォルト値を持つことは許可されていません。
class Demo {
protected readonly string $foo = "bar";
}
この文は定義し、初期化します
$foo初期化後にその値を変更できないので、プロパティは実質的に定数です。その結果、デフォルト値は禁止されており、実際の定数を使用する必要があります。
class Demo {
const foo = "bar";
}
この制限に続いて、
readonlyはタイプ付きプロパティのみサポートされています。次のプロパティには無効な定義があります:
class Demo {
protected readonly $foo;
}
型指定されていないプロパティ、例えば
$foo上記には、暗黙のデフォルト値があります。
nullもし
readonly許可された場合、「暗黙の定数はなし」というルールが再浮上することになります。型付きプロパティは「未初期化」と「null」の状態を区別するため、明示的に設定するまで値を持たない状態で存在します。
readonly修飾子は、クラスの継承の一部として使用される際に特別なルールがあります。子クラスは追加や削除できません。
readonly親によって定義されたプロパティに基づいて。
書き込み可能なプロパティを作成する
readonlyそのメソッドが値を変異させる場合、親クラスを壊すことになります。制約を取り除くことは一見無害に思えますが、RFCは次のように見ています。
readonly「意図的制限」として、継承のオーバーライドを許可した場合に失われる機能の制限として、親クラスが子クラスが読み取り専用であるべきプロパティを変更することによって副作用を引き起こせないことを主張できるようにするために禁止されています。
読み取り専用プロパティは、定義されているスコープ内でのみ設定できます。これはつまり、
publicプロパティはクラスの外部から設定することはできません。たとえそれが事前に初期化されていなくても:
class Demo {
public readonly string $foo;
}
$d = new Demo();
$d -> foo = "bar"; // illegal
初期化はプロパティを定義するクラス内で行う必要があります。そのため、readonlyプロパティは他のプログラミング言語の不変フィールドに近く、既存のPHPプロパティとは異なります。
その
readonly修飾子はすべての書き込みに平等に適用されます。内部アクセスと外部アクセスを区別しません。クラス内で書き込み可能でありながら、公開されているreadonlyのプロパティを持つことはできませんが、将来の仕様拡張によって許可される可能性があります。
最後の注意点は、
cloneキーワード。このコードは動作しません:
class Demo {
public function __construct(
public string $foo
) {}
}
$d = new Demo("bar");
$d2 = clone $d;
$d2 -> foo = "foobar";
クローンは通常のプロパティアクセスと同じルールに従います。たとえ変更があっても
foobar初めてのことです
fooにアクセスされる
$d2そのプロパティは、クローンプロセスによってすでに初期化されています。クローン時に暗黙的な初期化があります。
readonlyプロパティをいつ使用するべきか?
読み取り専用プロパティは、データ構造を表すシンプルなクラスの作成を大幅に加速します。HTTPリクエストパラメータ、データ転送オブジェクト、レスポンスデータを保持するために使い捨てのクラスを書くことは一般的です。これらは通常、イミュータブルであり、クラスが構築された後にプロパティが変更されることは期待されていません。
構造体のようなクラスを書く際には、かつては魅力に欠ける二つの選択肢しかありませんでした:公開プロパティを使用して開発を早めるが、変更を許可するか、保護されたプロパティを公開するためにゲッターメソッドを手動で追加するための時間を費やすかのどちらかです。
// Not ideal - Properties could be modified externally
class UserCreationRequest {
public function __construct(
public string $Username,
public string $Password
) {}
}
// Not ideal either - Lots of boilerplate code
class UserCreationRequest {
public function __construct(
protected string $Username,
protected string $Password
) {}
public function getUsername() : string {
return $this -> Username;
}
public function getPassword() : string {
return $this -> Password;
}
}
読み取り専用プロパティにより、理想的なアプローチがついに可能になりました。
class UserCreationRequest {
public function __construct(
public readonly string $Username,
public readonly string $Password
) {}
}
プロパティは公共にアクセス可能ですが不変です。コンストラクタプロパティのプロモーションと組み合わせることで、readonlyプロパティはボイラープレートコードを大幅に削減し、より迅速に便利なクラスを書くことを約束します。
readonlyまた、コードの可読性を高め、あなたの意図をより明確に示すのに役立ちます。読んでいる人や編集している人が
UserCreationRequestクラスはそのプロパティが変更されるべきでないことを知っています。最初の例では、プロジェクト内の他のコードがクラスのプロパティを直接変更するかどうかは不明です。2番目の例は少し明確ですが、依然として開発者に冗長な実装を誘発させる可能性があります。
setUsername()そして
setPassword()方法。
結論
ザ
readonly修飾子はPHPクラスプロパティに組み込みの不変性サポートを提供します。これにより、コードが明確になり、実行時に不変性を強制することで意図しない値の変更を防ぎます。
PHP 7のリリースシリーズを振り返ると、基本的な構造体のようなクラスを作成するには、型付きプロパティを定義し、それらのプロパティを設定するコンストラクタを書き、値を公開するためのゲッターメソッドを追加する必要がありました。しかし、PHP 8.1では、それらをすべて1つのコンストラクタのシグネチャにまとめることができます。
public readonlyおよび不動産の促進。
読み取り専用プロパティは、最新のPHP 8.1開発ビルドに実装されています。製品版のリリースは2021年11月に到着する予定です。
