编译器可以通过#[derive]为一些trait提供基础的实现。 如果需要更复杂的逻辑,这些trait也可以被手动实现。
这些可导入的实现:
Debug trait 用于开启格式化字符串中的调试格式,其通过在 {} 占位符中增加 :? 表明。
Debug trait 允许以调试目的来打印一个类型的实例,所以使用该类型的程序员可以在程序执行的特定时间点观察其实例。
例如,在使用 assert_eq! 宏时,Debug trait 是必须的。如果等式断言失败,这个宏就把给定实例的值作为参数打印出来,如此程序员可以看到两个实例为什么不相等。
#[derive(Debug)]
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 是必须的。
#[derive(Debug, Clone, Copy, Ord, Eq, PartialOrd, PartialEq, Hash)]
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;
#[derive(Eq)]
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 的更多信息。
#[derive(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;
#[derive(Debug, Hash)]
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 。
#[derive(Default,Debug)] //(Debug是为了方便打印)
struct MyTest{
i:i32,
j:Option<i32>,
k:String,
}
fn main(){
let mt = MyTest::default();
println!("{:?}",mt);
}
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved