Rust常用特型之Default特型

文章介绍了Rust标准库中的Default特型,它允许类型提供一个默认值。字符串、集合和其他类型如DrawParameters如何实现Default,以及在结构体赋值、元组和引用计数类型中的应用。
摘要由CSDN通过智能技术生成

在Rust标准库中,存在很多常用的工具类特型,它们能帮助我们写出更具有Rust风格的代码。

某些类型可以有一个有意义的默认值,例如默认的向量或者字符串是空的,默认的数字为0,默认的Option是None等。

这样的类型可以实现std::default::Default特型:

trait Default {
fn default() -> Self;
}

该特型很简单,就只有一个关联函数default,用于返回自身类型的一个新的值。

我们来看字符串String对该特型的实现,非常简单:

impl Default for String {
fn default() -> String {
  String::new()
  }
}

所以字符串的默认值就是一个新的空字符串.所有Rust的集合类型,Vec,HashMap,BinaryHeap等,都实现了Default特型,它们的default函数返回一个空的集合。这在你需要先建立一个集合,以后再向里面插入值时非常有用,因为你建立集合时不需要指定其中元素的类型,在第一次插入值时决定。

例如 Iterator特型的partition函数 把迭代器产生的值分离成两个集合,它使用一个闭包函数来决定哪个值去哪个集合。

use std::collections::HashSet;
let squares = [4, 9, 16, 25, 36, 49, 64];
let (powers_of_two, impure): (HashSet<i32>, HashSet<i32>)
  = squares.iter().partition(|&n| n & (n-1) == 0);
assert_eq!(powers_of_two.len(), 3);
assert_eq!(impure.len(), 4);

闭包函数使用位操作符来查找哪些数是2的幂,partition函数使用它产生两个HashSet。当然,partition函数并不是只能产生HashSet,你可以使用它产生任何类型的集合,只要该集合实现了DefaultExtend<T>特型,前者它会产生一个新的空集合,后者是将产生的值添加到集合中去。String 也实现了DefaultExtend<char>特型,因此你可以这样写:

let (upper, lower): (String, String)
  = "Great Teacher Onizuka".chars().partition(|&c|c.is_uppercase());
assert_eq!(upper, "GTO");
assert_eq!(lower, "reat eacher nizuka");

Default特型另一个常见的应用场景为多字段结构体赋值。如果一个结构体有很多字段,但是其中绝大多数字段的值是固定的,很少变化的。因此我们构造结构体时只需要给出少数几个需要设定的字段就行了,其它的固定字段使用一个默认值就行。例如glimu::DrawParameters结构体有24个字段,每个字段都用来控制OpenGL怎么渲染图形中的某些位。而glium draw函数使用一个DrawParameters 结构体作为参数,由于它实现了Default,你可以这样写:

let params = glium::DrawParameters {
    line_width: Some(0.02),
    point_size: Some(0.02),
    .. Default::default()
};
target.draw(..., &params).unwrap();

这里我们只需要写出该结构体的两个字段 line_width和point_size,其它的都使用默认值。Default::default()会创建一个包含默认初始化值的DrawParameters结构体(这里为什么创建的值的类型是DrawParameters?因为Rust会自动推断,当然你也可以写 DrawParameters::default(),这样会多拼几个字母)。..语法是解构,和Javascript类似,就是余下的字段全部从这里获取,但是有一眯注意,它必须出现在结构体构造的最后一行(Javascript没有这个限制)。

如果一个T类型实现了Default,Rust 标准库也为Rc<T>,Arc<T>Box<T>, Cell<T>, RefCell<T>, Cow<T>, Mutex<T>

RwLock<T>自动实现了Default特型。例如,Rc<T>的默认值就是一个指向T默认值的Rc指针。如果元组的所有元素实现了Default,那么该元组(tuple)也自动实现了Default特型。它的默认值就是一个容纳了每个元素默认值的元组。

Rust 并没有为结构体自动实现Default特型。但是如果结构体所有的字段都实现了Default,那么你可以简单的在结构体定义上面添加#derive(Default)]来为该结构体自动实现Default特型。如果该结构体不符合这个条件,那么即使你手动添加了派生宏,也不会有效果。

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AiMateZero

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值