「Rust条记」Rust之derive特性总结
弁言
编译器可以经过#[derive]为一些trait提供基本的完成。 假如必要更繁复的逻辑,这些trait也可以被手动完成。
这些可导入的完成:
- 比力:Eq、PartialEq、Ord、PartialOrd
- Clone:从&T的一个拷贝创建T
- Copy:把一个典范的move转换为copy
- Hash:从&T盘算它的哈希
- Default:创建一个数据典范的空实例
- Debug: 用{:?}格式化一个值
Debug 用于步骤员输入
Debug trait 用于开启格式化字符串中的调试格式,其经过在 {} 占位符中增长 :? 标明。
Debug trait 允许以调试目标来打印一个典范的实例,以是使用该典范的步骤员可以在步骤实行的特定时间点察看但是例。
比如,在使用 assert_eq! 宏时,Debug trait 是必需的。假如等式断言失败,这个宏就把给定实例的值作为参数打印出来,云云步骤员可以看到两个实例为什么不相称。
struct ImportantExcerpt<'a>{
part: &'a str,
}
fn main() {
let novel = String::from("Call me Ishmael. Some years ago...");
let first_sentence = novel.split('.').next().expect("Could not find a '.'");
let i = ImportantExcerpt { part: first_sentence };
println!("{:?}",i);
}
等值比力的 PartialEq 和 Eq
PartialEq trait 可以比力一个典范的实例以反省对否相称,并开启了 == 和 != 运算符的功效。
派生的 PartialEq 完成了 eq 办法。当 PartialEq 在布局体上派生时,仅有一切 的字段都相称时两个实例才相称,同时只需有任何字段不相称则两个实例就不相称。当在摆列上派生时,每一个成员都和其本身相称,且和其他成员都不相称。
比如,当使用 assert_eq! 宏时,必要比力比力一个典范的两个实例对否相称,则 PartialEq trait 是必需的。
enum Endpoint {
OauthToken,
Disciplines,
PublicTournaments,
MyTournaments,
Matches,
}
lazy_static! {
static ref API_EP: HashMap<Endpoint, &'static str> = {
let mut m: HashMap<Endpoint, &'static str> = HashMap::new();
m.insert(Endpoint::OauthToken,"/oauth/v2/token");
m.insert(Endpoint::Disciplines,"/v1/disciplines");
m.insert(Endpoint::PublicTournaments,"/v1/tournaments");
m.insert(Endpoint::MyTournaments,"/v1/me/tournaments");
m.insert(Endpoint::Matches,"/v1/tournaments/{}/matches");
m
};
}
序次比力的 PartialOrd 和 Ord
PartialOrd trait 可以基于排序的目标而比力一个典范的实例。完成了 PartialOrd 的典范可以使用 <、 >、<= 和 >= 利用符。但只能在同时完成了 PartialEq 的典范上使用 PartialOrd。
use std::cmp::Ordering;
struct Person {
id: u32,
name: String,
height: u32,
}
impl PartialOrd for Person {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Person {
fn cmp(&self, other: &Self) -> Ordering {
self.height.cmp(&other.height)
}
}
impl PartialEq for Person {
fn eq(&self, other: &Self) -> bool {
self.height == other.height
}
}
复制值的 Clone 和 Copy
Clone trait 可以明白地创建一个值的深拷贝(deep copy),复制历程约莫包含随意代码的实行以及堆上数据的复制。查阅第四章 “变量和数据的交互办法:挪动” 以获取有关 Clone 的更多信息。
struct Morpheus {
blue_pill: f32,
red_pill: i64,
}
fn main() {
let f = Morpheus { blue_pill: 0.0, red_pill: 0 };
let copy = f.clone(); // and now we can clone it!
}
安稳轻重的值到值映射的 Hash
Hash trait 可以实例化一个随意轻重的典范,并且可以用哈希(hash)函数将该实例映射到一个安稳轻重的值上。派生 Hash 完成了 hash 办法。hash 办法的派生完成团结了在典范的每局部调用 hash 的后果,这意味着一切的字段或值也必需完成了 Hash,如此才干够派生 Hash。
比如,在 HashMap<K, V> 上存储数据,存放 key 的时分,Hash 是必需的。
use std::collections::HashMap;
struct Man{
pub age: i32,
pub name: String,
}
impl PartialEq for Man{
fn eq(&self, other: &Self) -> bool {
(self.age == other.age) && (self.name == other.name)
}
}
impl Eq for Man{}
fn test_1(){
let x1 = Man{
age: 11,
name: String::from("tim"),
};
let x2 = Man{
age: 12,
name: String::from("sam"),
};
let x3 = Man{
age: 11,
name: String::from("tim"),
};
let mut ahash = HashMap::new();
ahash.insert(&x1, 1i32);
}
fn main() {
test_1();
}
默许值的 Default
Default trait 使你创建一个典范的默许值。 派生 Default 完成了 default 函数。default 函数的派生完成调用了典范每局部的 default 函数,这意味着典范中一切的字段或值也必需完成了 Default,如此才干够派生 Default 。
//(Debug是为了便利打印)
struct MyTest{
i:i32,
j:Option<i32>,
k:String,
}
fn main(){
let mt = MyTest::default();
println!("{:?}",mt);
}