トークン型

プライベートなコンストラクタを持つ型は、不変条件の証明として利用できます。

// Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0

pub mod token {
    // モジュール境界の内側にある、プライベートフィールドを持つ公開型。
    pub struct Token { proof: () }

    pub fn get_token() -> Option<Token> {
        Some(Token { proof: () })
    }
}

pub fn protected_work(token: token::Token) {
    println!("We have a token, so we can make assumptions.")
}

fn main() {
    if let Some(token) = token::get_token() {
        // トークンがあるので、この作業を実行できます。
        protected_work(token);
    } else {
        // トークンを取得できなかったので、`protected_work` を呼び出せません。
    }
}
  • 動機: ユーザーが特定のタスクを実行するまで、機能へのアクセスを 制限できるようにしたい。

    これは、struct と module のプライバシールールを通じて、API の利用者が 自分では構築できない型を定義することで実現できます。

    Newtypes も同様の方法でプライバシールールを使い、 値が実行時に不変条件を満たすことが保証されない限り、構築を 制限します。

  • 問い: ここでの proof: () フィールドの目的は何ですか?

    proof: () がなければ、Token にはプライベートフィールドがなくなり、 ユーザーは Token の値を任意に構築できるようになります。

    実演: main でトークンを手動で構築してみて、コンパイルエラーを 示してください。実演: Token から proof フィールドを削除して、 プライベートフィールドがなければユーザーが Token を構築できることを示してください。

  • Token 型をモジュール境界 (token) の内側に置くことで、その モジュールの外側のユーザーは proof フィールドにアクセスする権限がないため、 自分でその値を構築できません。

    API 開発者は、これらのトークンを生成するメソッドや関数を定義できます。 ユーザーにはできません。

    そのトークンは、API 開発者がそのトークンへのアクセスに対して定めた条件を 満たしたことの証明になります。

  • 問い: API 開発者が、これを回避する手段を誤って持ち込んでしまうのは どのような場合でしょうか?

    「シリアライズ実装」、ほかのパーサー / 「from string」実装、 または Default の実装といった答えを期待します。