3.1 Newtype 模式
Newtype 模式 — Comprehensive Rust
译文 · 基于 Comprehensive Rust
原文链接: https://google.github.io/comprehensive-rust/idiomatic/leveraging-the-type-system/newtype-pattern.html
3.1 Newtype 模式
Newtype 是对已有类型(常为原始类型)的包装:
1
2
3
4
| // Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
/// 唯一用户标识符,实现为围绕 `u64` 的 newtype。
pub struct UserId(u64);
|
与类型别名不同,newtype 不能与被包装类型互换使用:
1
2
3
4
5
6
7
8
9
10
11
| // Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
pub struct UserId(u64);
fn needs_user(user: UserId) {
// ...
}
fn main() {
needs_user(1); // 🛠️❌
}
|
Rust 编译器也不允许你直接使用底层类型上定义的方法或运算符:
1
2
3
4
5
6
7
| // Copyright 2025 Google LLC
// SPDX-License-Identifier: Apache-2.0
pub struct UserId(u64);
fn main() {
assert_ne!(UserId(1), UserId(2)); // 🛠️❌
}
|
学员应已在「基础知识」课程中接触过 newtype 模式,当时学习了
元组结构体。
运行示例,向学员展示编译器给出的错误信息。
把示例改成用类型别名而非 newtype,例如 type MessageId = u64。修改后的示例应能通过编译,从而突出两种做法的差异。
强调:开箱即用的 newtype 本身没有附着行为。你需要有意识地决定愿意从底层类型转发哪些方法和运算符。在 UserId 例子中,允许 UserId 之间比较是合理的,但不允许加、减等算术运算。
01-语义混淆 — Comprehensive Rust
02-强制不变量 — Comprehensive Rust
03-真的封装了吗? — Comprehensive Rust