(jp) =
<!–
–>

PHP のジェネリック。 私はそれらが欲しいことを知っています。 そして、私は同意する多くの開発者を知っています。 一方、ジェネリックスとは何か、またはジェネリックを気にする必要がある理由を知らないと言う PHP プログラマーのグループ (おそらくそれ以上) がいます。
このブログでは、ジェネリックと PHP について連載を行う予定です。 最初から始めますが、より複雑なトピックにすぐに進みます。 ジェネリックとは何か、PHP がジェネリックをサポートしない理由、そして将来何が可能になるかについて説明します。
始めましょう。
すべてのプログラミング言語には、ある種の型システムがあります。 非常に厳格な実装を持つ言語もあれば、PHP はこのカテゴリに属し、はるかに寛容な言語もあります。
現在、型システムはさまざまな理由で使用されています。 最も明白なものは タイプ検証.
2 つの数値、2 つの整数を受け取る関数があるとします。 そしてそれらに対してある種の数学演算を行います:
function add($a, $b)
return $a + $b;
PHP では、数値、文字列、ブール値など、あらゆる種類のデータをその関数に渡すことができます。 PHP は、変数を足し合わせるなど、変数が意味をなすときはいつでも変数を変換するために最善を尽くします。
add('1', '2');
しかし、これらの変換 (型のジャグリング) は、言うまでもなく、バグやクラッシュなどの予期しない結果につながることがよくあります。
add([], true);
これで、数学の追加が特定の入力で機能するかどうかを確認するコードを手動で書くことができます。
function add($a, $b)
if (!is_int($a)
または、PHP に組み込まれている型ヒントを利用することもできます。
function add(int $a, int $b): int
return $a + $b;
PHP コミュニティの多くの開発者は、この関数に整数のみを渡す必要があることを知っているため、これらの型ヒントはあまり気にしないと言っています。
ただし、そのような推論はすぐに崩壊します。多くの場合、そのコードベースで作業しているのはあなただけではありません。また、自分で書いていないコードも使用しています。composer で取り込んでいるパッケージの数を考えてみてください。 したがって、この例だけではそれほど大したことではないように見えるかもしれませんが、コードが大きくなり始めると型チェックが役立ちます。
それに加えて、型ヒントを追加すると、無効な状態を防ぐだけでなく、 明らかにする プログラマーである私たちからどのような入力が期待されるか。 関数が行うことの多くは、その型定義によってすでにカプセル化されているため、型によって外部ドキュメントを読む必要がなくなることがよくあります。
IDE はこの原則を大いに利用しています。つまり、クラスに属しているため、関数によって期待される入力の種類や、オブジェクトで使用できるフィールドとメソッドをプログラマーに伝えることができます。 IDE を使用すると、コードベース全体の型ヒントを静的に分析できるため、コード作成の生産性が大幅に向上します。
その言葉を心に留めておいてください: 静的解析 — このシリーズの後半で非常に重要になります。 つまり、プログラム、IDE、またはその他の種類の「静的アナライザー」がコードを見て、コードを実行しなくても、コードが機能するかどうか (少なくともある程度は) を知ることができます。 整数を取る関数に文字列を渡すと、IDE は何か間違ったことをしている、つまり実行時にプログラムがクラッシュする原因になることを教えてくれます。 しかし、IDE は実際にコードを実行しなくても教えてくれます。
一方、型システムには限界があります。 一般的な例は「アイテムのリスト」です。
class Collection extends ArrayObject
public function offsetGet(mixed $key): mixed
public function filter(Closure $fn): self
public function map(Closure $fn): self
コレクションには、あらゆる種類の入力で機能する一連のメソッドがあります。ループ、フィルタリング、マッピングなどです。 コレクションの実装は、文字列を扱っているか整数を扱っているかを気にするべきではありません。
しかし、部外者の視点から見てみましょう。 あるコレクションに文字列のみが含まれ、別のコレクションには文字列のみが含まれていることを確認したい場合はどうなりますか User オブジェクト。 コレクション自体はアイテムをループするときに気にしませんが、私たちは気にします。 ループ内のこの項目が User なのか文字列なのかを知りたいのですが、これは大きな違いです。 しかし、適切な型情報がなければ、IDE は暗闇の中で動作しています。
$users = new Collection();
foreach ($users as $user)
$user->
これで、コレクションごとに個別の実装を作成できます。1 つは文字列のみで動作し、もう 1 つは文字列のみで動作します。 User オブジェクト:
class StringCollection extends Collection
public function offsetGet(mixed $key): string
class UserCollection extends Collection
public function offsetGet(mixed $key): User
しかし、3 つ目の実装が必要な場合はどうでしょうか。 4番目? 10か20かもしれません。 そのすべてのコードを管理するのは非常に面倒です。
そこでジェネリックの出番です。
はっきりさせておきますが、PHP にはジェネリックがありません。 これはかなり多くの手を抜いた大胆な声明であり、このシリーズの後半で再び取り上げます。 しかし、今のところ、次に示すことは PHP では不可能であると言えば十分です。 しかし、それは他の多くの言語にあります。
多くのプログラミング言語では、考えられる型ごとに個別の実装を作成する代わりに、開発者がコレクション クラスで「ジェネリック」型を定義できるようになっています。
class Collection<Type> extends ArrayObject
public function offsetGet(mixed $key): Type
基本的に、コレクション クラスの実装はあらゆる種類の入力に対して機能すると言っていますが、コレクションのインスタンスを作成するときは、型を指定する必要があります。 これは一般的な実装ですが、プログラマーのニーズに応じて具体的に作成されています。
$users = new Collection<User>();
$slugs = new Collection<string>();
型を追加するのは簡単なことのように思えるかもしれません。 しかし、そのタイプだけが可能性の世界を開きます。 私たちの IDE は、コレクション内のデータの種類を認識し、間違ったタイプのアイテムを追加しているかどうかを教えてくれます。 コレクションを反復するときにアイテムで何ができるかを教えてくれます。また、それらの特定のアイテムを操作する方法を知っている関数にコレクションを渡しているかどうかを教えてくれます。
技術的には、必要なすべてのタイプのコレクションを手動で実装することで同じことを実現できます。 汎用的な実装は、コードを作成して保守している開発者であるあなたや私にとって大きな改善となるでしょう。
では、なぜ PHP にジェネリックがないのでしょうか? 退屈なコレクション以外に何ができるでしょうか? それらのサポートを追加できますか? このミニ シリーズでは、これらすべての質問にお答えします。 前もって明確にしておくと、このシリーズの目的はジェネリックについて説明することですが、それと同様に重要なのは、PHP で見逃していることを認識してもらいたいということです。 それを変えてほしい。
//platform.twitter.com/widgets.js