![Rust设计模式 —— 新类型](/_astro/rust-logo.sQffSkDS_ZJI3qB.webp)
Rust设计模式 —— 新类型
绕过孤儿规则,给标准库和第三方库的类型增加新成员函数
![Avatar](/_astro/_avatar.B-jQIxXa_ZRo5Hk.webp)
类似于Swift,Rust的类型系统允许我们在不触碰源码的情况下给其他crate的类型增加新的trait。这是一个极为方便的功能,可是,为了防止这种功能破坏了类型的一致性,Rust设定了孤儿规则,也就是孤儿规则。简单来说,孤儿规则允许我们为一个外部crate的类型拓展自定义的trait,或者为某个我们自定义的类型拓展某个外部crate的trait。这两者只能二选一,而不能同时满足。但是有时候,这种需求是真实存在的。此时,我们只能够采取一种方法绕过这一个规则,也就是所谓的新类型模式
新类型模式
新类型模式总体来说还是比较简单的,他的总体思路是将某个外部类型用某个自定义的类型包起来,通常是一个tuple,由于Rust的编译器的优化,事实上这一层抽象并没有引入额外的内存空间。
我们可以这样引入一个新类型:
pub struct MyCollection(pub Vec<i32>);
这样,我们就可以实现一些类型,例如:
impl FromStr for MyCollection {}
当然,我们也可以实现泛型化的新类型:
pub struct MyCollection<T>(pub Vec<T>);
这样,我们就可以通过类似于访问tuple内部元素的方法去访问这个类型
let my_collection: MyCollection = MyCollection(vec![1, 2, 3]);
println!("{:#?}", my_collection.0)
Deref
有些文章说我们应该为新类型实现deref来让系统自动解引用以省去这奇怪的.0
。但是,根据从Rust社区的反馈来看,这一行为更多的是被认为是一种反模式。相比之下,用模式匹配作解构是更加被推荐的一种方式
let MyCollection(arr) = my_collection; // arr 就是内部包含的类型