Newtype パターン

newtype は既存の型(多くの場合はプリミティブ型)を包むラッパーです。

// 著作権 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0

/// `u64` を包む newtype として実装された、一意のユーザー識別子。
pub struct UserId(u64);

型エイリアスとは異なり、newtype は包んでいる型と相互に置き換えることはできません。

// 著作権 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0

pub struct UserId(u64);

fn needs_user(user: UserId) {
    // ...
}

fn main() {
    needs_user(1); // 🛠️❌
}

また、Rust コンパイラは、基になる型に定義されたメソッドや演算子を使うことも許可しません。

// 著作権 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0

pub struct UserId(u64);

fn main() {
    assert_ne!(UserId(1), UserId(2)); // 🛠️❌
}
  • 受講者は、タプル構造体 について 学んだ「Fundamentals」コースで、newtype パターンに触れているはずです。

  • 例を実行して、コンパイラからのエラーメッセージを受講者に示してください。

  • newtype の代わりに型エイリアスを使うように例を変更してください。たとえば type MessageId = u64 です。修正後の例はコンパイルできるはずで、それによって 2 つのアプローチの違いが明確になります。

  • newtype には、何もしなければ振る舞いが何も備わっていないことを強調して ください。基になる型からどのメソッドや演算子を転送してよいかは、意図的に 決める必要があります。この UserId の例では、UserId 同士の比較を許可 するのは妥当ですが、加算や減算のような算術演算を許可するのは意味がありま せん。