rust实战 - newtype模式
什么是newtype
简单的说,就是用元组结构体将已有类型包裹起来:struct Meters(u32)
newtype的优点:
- 自定义类型可以让我们给出更有意义和可读性的类型名,比如
struct Year(u32)
- 某些场景,只有newtype可以很好的解决
- 隐藏内部类型的细节
自定义类型给出更有意义的命名
struct Years(i64);
struct Days(i64);
impl Years {
pub fn to_days(&self) -> Days {
Days(self.0 * 365)
}
}
impl Days {
/// truncates partial years
pub fn to_years(&self) -> Years {
Years(self.0 / 365)
}
}
在外部类型上实现外部trait
rust限定只有当类型和对应trait中的任意一个定义在本地包内时,才能够为该类型实现trait,叫做孤儿规则。
比如你不能Vec
通过newtype类型可以绕过孤儿规则,实现是利用元组结构体创建出新的类型。并且不会造成任何运行时开销,新类型会在编译过程中被优化掉。
use std::{fmt, ops::Deref};
struct Wrapper(Vec<String>);
impl fmt::Display for Wrapper {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
}
impl Deref for Wrapper {
type Target = Vec<String>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
fn main() {
let w = Wrapper(vec![String::from("hello"),
String::from("world")]);
println!("w = {}", w);
println!("wrapper can use vec function join, join result is: {}", w.join(","));
}
因为Wrapper是一个新的类型,所以它没有自己内部值的方法。为了让Wrapper的行为与Vec
封装内部细节
#[derive(Debug)]
struct WrapperStr(String);
fn main() {
let s = "Hello World".to_string();
let mut w = WrapperStr(s);
println!("{:?}", w);
// 隐藏了被包装String的方法
// 但仍然可以通过下面方式调用
// w.0.push_str(" !");
// println!("{:?}", w);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署