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实现fmt::Display。

通过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完全一致,我们需要在Wrapper中实现所有Vec的方法,并将这些方法委托给self.0。假如我们希望新类型具有内部类型的所有方法,那么我们也可以为Wrapper实现Deref trait来直接返回内部的类型。假如我们不希望Wrapper类型具有内部类型的所有方法,比如在需要限制Wrapper类型的行为时,我们就只能手动实现需要的那部分方法了。

封装内部细节

#[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);   
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值