選言的標準形のサポート
PHP 8.2では、選言的標準形(Disjunctive Normal Form Types)がサポートされました。「選言的」(disjunctive)という言葉が分かりにくいのですが、論理積(AND)を含んだ論理式を論理和(OR)で結合したものを型に指定できること、と思えばよいでしょう。
もともとは、論理学において命題と命題を「または」で結合することをいいます。要は、PHP 8.0でサポートされた交差型とPHP 8.1でサポートされたUNION型の結合を定めたもの、ということができます。この理解のために、まずはUNION型と交差型を紹介しておきます。
UNION型[PHP 8.0]
UNION型を利用することで、「複数の型のいずれか」という型を表現できます。
従来から、関数の引数/戻り値などに型を指定できましたが、まずは、intならint、floatならfloatと、特定の型を指定するのが基本です。指定された型以外の値を与えようとすると、TypeErrorが発生します。これを、ときにはint、ときにはfloatというように複数の型を表現するのがUNION型です。
UNIONとは、数学でいう和集合を意味します。つまり、「または」(OR、論理和)という関係となります。以下のように、許容する型を論理和で使われる縦バー「|」で結んで指定します。
public int|float $value = 0; // intとfloatを受け入れるプロパティ
public function add(int|float $a, int|float $b): int|float {}
// int/float型の引数を受け入れて、そのどちらかの型を返すメソッド
交差型[PHP 8.1]
交差型では、関数の引数や戻り値、クラスのプロパティなど型の指定が可能な箇所において、型の制約を指定できます。UNION型の和集合に対し、交差型のintersectionとは数学の共通集合を意味しています。つまり、交差型はAND(論理積、「かつ」という関係になります。以下のように、許容する型を論理積で使われるアンパサンド「&」で結んで指定します。
public X&Y $value; // XとY双方を継承するプロパティ
交差型で指定できる型はクラスとインタフェースに限定されています。intなどのプリミティブ型にANDを適用しても共通部は存在しないからです。このように交差型は、特定のクラスやインタフェースを継承しているなどの条件を、引数や戻り値に指定することが主な目的となります。
選言的標準形[PHP 8.2]
ここで、選言的標準形です。PHP 8.1までは、せっかくの新機能であるUNION型と交差型を組み合わせて使えないという制約がありました。例えば「型Aかつ型Bである必要があるが、型Cでもよい」といった指定です。選言的標準形では、このような制約がなくなります。
以下のリストは、宣言型標準形の例です。valueプロパティが、int型もXandY型も受け入れることが分かります。なお、選言的標準形は、交差型のANDをUNION型のORで結合するためのものなので、ANDの方をカッコで囲っていることに要注意です。
// インタフェースを2つ定義する
interface X {}
interface Y {}
class XandY implements X, Y {} // 両方を継承したクラスを定義する
class DisjunctiveSample {
public int|(X&Y) $value; // intまたは、XかつYというプロパティ
}
$t = new DisjunctiveSample();
$t->value = 100; // intなのでOK
$t->value = new XandY(); // XandYはXとYを実装しているのでOK
選言的標準形は、あくまでも命題同士をORで連結する仕組みであるため、例えば以下のような記述(XまたはYで、かつZ)はできません。
public (X|Y)&Z $bad; // これはできない
null型とfalse型、true型[PHP 8.2]
null型とfalse型は、PHP 8.0でサポートされました。それぞれ、null、falseのみを値として持つことができる型で、UNION型においてのみnullやfalseを受け入れることのできる疑似型として導入されました。
PHP 8.2では、null型とfalse型は疑似型ではない、単独でも使用できる通常の型として使えるようになりました。nullしか返さない、falseしか返さない関数などを定義できるので、例えばテストコードにてこのような関数を記述する必要のある場合に利用できるでしょう。
さらに、false型に加えてtrue型もサポートされました。true型により、trueしか返さない関数などを定義できます。false型があってtrue型がないのは中途半端なわけですが、エラー時には例外を発生し、成功時にはtrueを返すといった関数をbool型を用いずに定義できるようになります。
以下のリストは、これらの型の使用例です。
class NewTypes {
public null $n = null;
public false $f = false;
public true $t = true;
public function func(null|int $a): null|true {
return $a;
}
}
$nt = new NewTypes();
$nt->n = true; // TypeErrorになる
$nt->f = null; // TypeErrorになる
$nt->t = false; // TypeErrorになる
$nt->func(10); // TypeErrorになる
never型
PHP 8.1でサポートされたnever型(関数から戻らないことを示す型)は、UNION型などで使えずに単独での使用のみとなっているので注意してください。int型を返す可能性もあるとしたら、never型の意味がないからです。
