(jp) =
型付きクラス プロパティが追加されました PHP 7.4 大幅な改善を提供します PHPの型システム。 これらの変更は完全にオプトインであり、以前のバージョンを壊すものではありません。
この投稿では、この機能を詳しく見ていきますが、まず最も重要なポイントを要約することから始めましょう。
- それらは現在利用可能です PHP 7.4、2019年11月発売予定
- これらはクラスでのみ使用でき、アクセス修飾子が必要です。
public
、protected
またprivate
; またvar
- を除くすべてのタイプが許可されます。
void
とcallable
実際の動作は次のとおりです。
class Foo
public int $a;
public ?string $b = 'foo';
private Foo $prop;
protected static string $static = 'default';
型の付加的なメリットがよくわからない場合は、まずこの投稿を読むことをお勧めします。
# 未初期化
楽しいことを見る前に、型指定されたプロパティについて、最初に説明することが不可欠な重要な側面があります。
一見するとどう思うかもしれませんが、次のコードは有効です。
class Foo
public int $bar;
$foo = new Foo;
の値にもかかわらず、 $bar
のオブジェクトを作成した後、整数ではありません Foo
、 PHP 場合にのみエラーをスローします $bar
アクセスされます:
var_dump($foo->bar);
Fatal error: Uncaught Error: Typed property Foo::$bar
must not be accessed before initialization
エラー メッセージから読み取れるように、新しい種類の「変数状態」があります: 初期化されていません。
もしも $bar
タイプがありませんでした。その値は単純に null
. ただし、型は null 許容になる可能性があるため、型指定された null 許容プロパティが設定されているのか、単に忘れられているのかを判断することはできません。 そのため、「未初期化」が追加されました。
uninitialized について覚えておくべき重要なことが 4 つあります。
- 初期化されていないプロパティから読み取ることはできません。これを行うと、致命的なエラーが発生します。
- プロパティにアクセスするときに初期化されていない状態がチェックされるため、その型が null 非許容であっても、初期化されていないプロパティを持つオブジェクトを作成できます。
- 読み取る前に、初期化されていないプロパティに書き込むことができます。
- 使用する
unset
型指定されたプロパティを設定すると初期化されなくなりますが、型指定されていないプロパティを設定解除すると初期化されますnull
.
特に、オブジェクトの作成後に初期化されていない null 非許容のプロパティが設定されている次のコードは有効であることに注意してください。
class Foo
public int $a;
$foo = new Foo;
$foo->a = 1;
初期化されていない状態はプロパティの値を読み取るときにのみチェックされますが、型の検証はプロパティに書き込むときに行われます。 これは、無効な型がプロパティの値になることはないと確信できることを意味します。
# デフォルトとコンストラクタ
型付きの値を初期化する方法を詳しく見てみましょう。 スカラー型の場合、デフォルト値を提供することが可能です:
class Foo
public int $bar = 4;
public ?string $baz = null;
public array $list = [1, 2, 3];
のみ使用できることに注意してください。 null
型が実際に null 許容である場合のデフォルトとして。 これは明らかなように思えるかもしれませんが、次のことが許可されているパラメーターの既定値には、従来の動作がいくつかあります。
function passNull(int $i = null)
passNull(null);
幸いなことに、この紛らわしい動作は型付きプロパティでは許可されていません。
また、デフォルト値を持つことは不可能であることに注意してください object
またはクラスの種類。 コンストラクタを使用してデフォルトを設定する必要があります。
型付きの値を初期化する明白な場所は、もちろんコンストラクターです。
class Foo
private int $a;
public function __construct(int $a)
$this->a = $a;
ただし、前に述べたことも覚えておいてください。コンストラクターの外部で、初期化されていないプロパティに書き込むことは有効です。 プロパティから何も読み取っていない限り、初期化されていないチェックは実行されません。
# 型の種類
では、正確には何をどのように入力できるのでしょうか? 型付きプロパティは (今のところ) クラスでのみ機能し、アクセス修飾子または var
その前にキーワード。
利用可能なタイプの時点で、ほとんどすべてのタイプが使用できます。 void
と callable
.
なぜなら void
は値がないことを意味しますが、値を入力するために使用できないことは理にかなっています。
callable
ただし、もう少し微妙です。
の「callable」を参照してください PHP 次のように記述できます。
$callable = [$this, 'method'];
次の(壊れた)コードがあるとします。
class Foo
public callable $callable;
public function __construct(callable $callable)
class Bar
public Foo $foo;
public function __construct()
$this->foo = new Foo([$this, 'method'])
private function method()
$bar = new Bar;
($bar->foo->callable)();
この例では、 $callable
プライベートを指す Bar::method
、しかしのコンテキスト内で呼び出されます Foo
. この問題のため、追加しないことにしました callable
サポート。
大したことじゃないんだけど、 Closure
は有効な型であり、 $this
構築されたコンテキスト。
邪魔にならないので、利用可能なすべてのタイプのリストを次に示します。
- ブール
- 整数
- 浮く
- ストリング
- 配列
- 反復可能
- 物体
- ? (ヌル可能)
- 自分と親
- クラスとインターフェース
# 強制型と厳密型
PHPは、私たちが好きで嫌いな動的言語であるため、可能な限り型を強制または変換しようとします。 整数が必要な場所に文字列を渡すとします。 PHP その文字列を自動的に変換しようとします:
function coerce(int $i)
coerce('1');
型付きプロパティにも同じ原則が適用されます。 次のコードは有効で、変換されます '1'
に 1
.
class Bar
public int $i;
$bar = new Bar;
$bar->i = '1';
この動作が気に入らない場合は、厳密な型を宣言して無効にすることができます。
declare(strict_types=1);
$bar = new Bar;
$bar->i = '1';
Fatal error: Uncaught TypeError:
Typed property Bar::$i must be int, string used
# タイプの差異と継承
それでも PHP 7.4 型分散の改善が導入されましたが、型付きプロパティは依然として不変です。 これは、以下が無効であることを意味します。
class A
class B extends A
class Foo
public A $prop;
class Bar extends Foo
public B $prop;
Fatal error: Type of Bar::$prop must be A (as in class Foo)
上記の例が重要でないように思われる場合は、次を参照してください。
class Foo
public self $prop;
class Bar extends Foo
public self $prop;
PHP 交換します self
コードを実行する前に、それが参照する具象クラスの舞台裏。 これは、この例で同じエラーがスローされることを意味します。 それを処理する唯一の方法は、次のことです。
class Foo
public Foo $prop;
class Bar extends Foo
public Foo $prop;
継承といえば、継承されたプロパティの型を上書きする適切なユース ケースを思いつくのは難しいかもしれません。
私はその意見に同意しますが、継承されたプロパティの型を変更することは可能ですが、アクセス修飾子も変更された場合に限ります。 private
に protected
また public
.
次のコードは有効です。
class Foo
private int $prop;
class Bar extends Foo
public string $prop;
ただし、型を null 許容から null 非許容に、またはその逆に変更することは許可されていません。
class Foo
public int $a;
public ?int $b;
class Bar extends Foo
public ?int $a;
public int $b;
Fatal error: Type of Bar::$a must be int (as in class Foo)
#まだまだあります!
この投稿の冒頭で述べたように、型付きプロパティは 選考科目 に加えて PHP. それらについては、まだまだ言いたいことがたくさんあります。 をお読みになることをお勧めします。 RFC すべてのきちんとした細部を知るために。
初めての方は PHP 7.4、変更と追加された機能の完全なリストをお読みになることをお勧めします。 正直なところ、これは過去最高のリリースの 1 つであり、時間を費やす価値があります。
最後に、このトピックについて共有したいご意見がありましたら、ぜひお聞かせください。 あなたは私に連絡することができます ツイッター または電子メール。
次回まで!