PHPの「悪しき自由」を断ち切る:Hackの `readonly` がもたらす静的な安心感
やあ。Hackの世界へようこそ。
PHPから移行してきた君たちが最初に直面する「壁」であり、同時に「最強の武器」となるのが、Hackの型システムだ。特に、大規模開発でバグの温床になりがちな「意図しないオブジェクトの書き換え(副作用)」。
PHPでは、関数にオブジェクトを渡すと、それは参照渡しのように振る舞い、どこかのスコープで値が書き換えられても検知できない。これが追跡困難なバグの元凶だ。
今回は、Hackが誇る強力な武器『readonlyプロパティ』を紐解こう。これを使えば、君のコードは「堅牢」の領域へと一歩踏み出せる。
—
1. なぜ「readonly」が必要なのか?(PHPとの違い)
PHPのクラスプロパティは、デフォルトで「誰からでも書き換え可能」だ。
// PHPの悪習:カプセル化が甘いとどこで書き換わったか分からない
class User {
public string $name;
}
$user = new User();
$user->name = “Alice”;
some_function($user); // ここで中身が書き換わっているかもしれない!
これに対し、Hackの `readonly` は「一度代入したら、二度と変えさせない」という契約をコンパイル時に強制する。これは単なる規約ではなく、HHVMの型チェッカーが監視する「物理的な制約」だ。
2. 基本的な書き方:不変性を担保する
Hackで readonly プロパティを定義するのは極めてシンプルだ。
namespace App;
class User {
// コンストラクタで初期化されたら、以後変更不可
public readonly string $username;
public function __construct(string $username) {
$this->username = $username;
}
}
function update_user(User $u): void {
// $u->username = “Bob”; // ← ここでHHVMの型チェックが即座にエラーを吐く!
// Typechecker Error: Cannot modify a readonly property.
}
ここがポイント:
もし君が `readonly` プロパティを書き換えようとすれば、コードを実行するまでもなく、IDEやコンパイル時に「その操作は許されない」と警告が出る。実行時のクラッシュを、開発段階で「消滅」させることができるんだ。
3. 陥りやすい罠:オブジェクトの「中身」は readonly ではない?
ここが初心者諸君がよく躓くポイントだ。`readonly` は「そのプロパティ自身」を保護するが、「その先のオブジェクトの内部」までは自動的に不変にはしない。
class Container {
public readonly Map
public function __construct(Map
$this->data = $data;
}
}
// 注意!
$c = new Container(Map {‘a’ => 1});
$c->data[‘a’] = 100; // これは通ってしまう可能性がある!
なぜか? `readonly` は「プロパティへの再代入(=別のMapへの差し替え)」を禁止しているだけで、Mapの中身を変更するメソッドの呼び出しまでは防げないからだ。
解決策:
Hackでは `readonly` と組み合わせて、「不変コレクション(ImmSetやImmMap)」を積極的に使うのが正解だ。
class SecureContainer {
// そもそも変更メソッドを持たない型を使う
public readonly ImmMap
public function __construct(ImmMap
$this->data = $data;
}
}
4. 先輩からのアドバイス:なぜこれを使うべきか
大規模なHackプロジェクトにおいて、バグの多くは「関数の副作用」から生まれる。
「この関数に渡すと、なぜか値が変わってしまう」……そんなデバッグに時間を溶かすのはもう終わりにしよう。
- readonly を使う利点:
1. 認知負荷の低下: `readonly` と書かれているだけで、その値は「初期化以降変わらない」と確信できる。読む側の脳のメモリ消費を劇的に抑えられるんだ。
2. スレッドセーフの布石: HHVMは並列処理の最適化を行うが、不変なデータは競合のリスクがない。`readonly` は将来のパフォーマンス向上のためのパスポートでもある。
3. 設計の強制: 「変えたいなら、新しいインスタンスを作れ」という設計思想(イミュータブルな設計)が、君のコードを自然と綺麗に保つ。
—
まとめ
Hackの `readonly` は、単なる修飾子ではない。君のコードを「予測可能な状態」に縛り付けるための、もっとも美しい制約だ。
まずは、自分の書くクラスのプロパティを「本当に書き換える必要があるか?」と自問自答してみよう。ほとんどの場合、`readonly` を付与できるはずだ。それができれば、君はもうHackの静的型システムの恩恵を十分に享受できている証拠だよ。
ここをクリアすれば、次は `shape` 型や `async/await` の深い森へ案内しよう。Hackの旅はまだ始まったばかりだ。また次回、コードの向こう側で会おう。