【入門編】Hackの『Readonly』プロパティ:PHPの可変オブジェクトによるバグを防ぐ – Hack言語 コア・静的型システムとHHVMのアーキテクチャ解析バイブル

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 $data;

public function __construct(Map $data) {
$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 $data;

public function __construct(ImmMap $data) {
$this->data = $data;
}
}

4. 先輩からのアドバイス:なぜこれを使うべきか

大規模なHackプロジェクトにおいて、バグの多くは「関数の副作用」から生まれる。
「この関数に渡すと、なぜか値が変わってしまう」……そんなデバッグに時間を溶かすのはもう終わりにしよう。

  • readonly を使う利点:

1. 認知負荷の低下: `readonly` と書かれているだけで、その値は「初期化以降変わらない」と確信できる。読む側の脳のメモリ消費を劇的に抑えられるんだ。
2. スレッドセーフの布石: HHVMは並列処理の最適化を行うが、不変なデータは競合のリスクがない。`readonly` は将来のパフォーマンス向上のためのパスポートでもある。
3. 設計の強制: 「変えたいなら、新しいインスタンスを作れ」という設計思想(イミュータブルな設計)が、君のコードを自然と綺麗に保つ。

—

まとめ

Hackの `readonly` は、単なる修飾子ではない。君のコードを「予測可能な状態」に縛り付けるための、もっとも美しい制約だ。

まずは、自分の書くクラスのプロパティを「本当に書き換える必要があるか?」と自問自答してみよう。ほとんどの場合、`readonly` を付与できるはずだ。それができれば、君はもうHackの静的型システムの恩恵を十分に享受できている証拠だよ。

ここをクリアすれば、次は `shape` 型や `async/await` の深い森へ案内しよう。Hackの旅はまだ始まったばかりだ。また次回、コードの向こう側で会おう。

タイトルとURLをコピーしました