结论:newtype 模式是用单字段元组结构体(struct Meters(f64))包装现有类型,得到一个全新的、不透明的类型。它零运行时开销,解决两类问题:类型安全(防止同底层类型的值混用)和绕过孤儿规则为外部类型实现外部 trait。
展开:1)类型安全:f64 既能是米也能是秒,函数签名 fn d(speed: f64) 拦不住单位传错;定义 Meters、Seconds 两个 newtype 后,混传直接编译错误,这是"让非法状态不可表示"的低成本实践。2)孤儿规则:impl Display for Vec<T> 不合法(trait 和类型都来自外部 crate),但 impl Display for MyVec(Vec<T>) 合法,因为 MyVec 是本地类型。代价是原类型的方法不再自动可用,需要 Deref、手动转发或 derive_more 之类的宏补齐——通常只暴露语义上合理的操作反而是好事。
struct Meters(f64);
struct Seconds(f64);
fn speed(d: Meters, t: Seconds) -> f64 { d.0 / t.0 }
// speed(Seconds(2.0), Meters(10.0)); // 编译错误:单位反了
易错点:newtype 与类型别名(type Meters = f64)完全不同——别名只是换名,不提供任何隔离。追问方向:HashMap<K,V> 的封装、类型级单位系统(uom crate)。