W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
appendix-03-derivable-traits.md
commit c07dddac692848ade6c2112c8e15a7087fbbec45
在本書的各個(gè)部分中,我們討論了可應(yīng)用于結(jié)構(gòu)體和枚舉定義的 derive
屬性。derive
屬性會(huì)在使用 derive
語法標(biāo)記的類型上生成對(duì)應(yīng) trait 的默認(rèn)實(shí)現(xiàn)的代碼。
在本附錄中提供了標(biāo)準(zhǔn)庫中所有可以使用 derive
的 trait 的參考。這些部分涉及到:
derive
? 提供什么樣的 trait 實(shí)現(xiàn)如果你希望不同于 derive
屬性所提供的行為,請(qǐng)查閱 標(biāo)準(zhǔn)庫文檔 中每個(gè) trait 的細(xì)節(jié)以了解如何手動(dòng)實(shí)現(xiàn)它們。
這里列出的 trait 是僅有的在標(biāo)準(zhǔn)庫中定義且能通過 derive
在類型上實(shí)現(xiàn)。標(biāo)準(zhǔn)庫中定義的其它 trait 不能通過 derive
在類型上實(shí)現(xiàn)。這些 trait 不存在有意義的默認(rèn)行為,所以由你負(fù)責(zé)以合理的方式實(shí)現(xiàn)它們。
一個(gè)無法被派生的 trait 的例子是為終端用戶處理格式化的 Display
。你應(yīng)該時(shí)??紤]使用合適的方法來為終端用戶顯示一個(gè)類型。終端用戶應(yīng)該看到類型的什么部分?他們會(huì)找出相關(guān)部分嗎?對(duì)他們來說最相關(guān)的數(shù)據(jù)格式是什么樣的?Rust 編譯器沒有這樣的洞察力,因此無法為你提供合適的默認(rèn)行為。
本附錄所提供的可派生 trait 列表并不全面:庫可以為其自己的 trait 實(shí)現(xiàn) derive
,可以使用 derive
的 trait 列表事實(shí)上是無限的。實(shí)現(xiàn) derive
涉及到過程宏的應(yīng)用,這在第十九章的 “宏” 有介紹。
Debug
trait 用于開啟格式化字符串中的調(diào)試格式,其通過在 {}
占位符中增加 :?
表明。
Debug
trait 允許以調(diào)試目的來打印一個(gè)類型的實(shí)例,所以使用該類型的程序員可以在程序執(zhí)行的特定時(shí)間點(diǎn)觀察其實(shí)例。
例如,在使用 assert_eq!
宏時(shí),Debug
trait 是必須的。如果等式斷言失敗,這個(gè)宏就把給定實(shí)例的值作為參數(shù)打印出來,如此程序員可以看到兩個(gè)實(shí)例為什么不相等。
PartialEq
trait 可以比較一個(gè)類型的實(shí)例以檢查是否相等,并開啟了 ==
和 !=
運(yùn)算符的功能。
派生的 PartialEq
實(shí)現(xiàn)了 eq
方法。當(dāng) PartialEq
在結(jié)構(gòu)體上派生時(shí),只有所有 的字段都相等時(shí)兩個(gè)實(shí)例才相等,同時(shí)只要有任何字段不相等則兩個(gè)實(shí)例就不相等。當(dāng)在枚舉上派生時(shí),每一個(gè)成員都和其自身相等,且和其他成員都不相等。
例如,當(dāng)使用 assert_eq!
宏時(shí),需要比較比較一個(gè)類型的兩個(gè)實(shí)例是否相等,則 PartialEq
trait 是必須的。
Eq
trait 沒有方法。其作用是表明每一個(gè)被標(biāo)記類型的值等于其自身。Eq
trait 只能應(yīng)用于那些實(shí)現(xiàn)了 PartialEq
的類型,但并非所有實(shí)現(xiàn)了 PartialEq
的類型都可以實(shí)現(xiàn) Eq
。浮點(diǎn)類型就是一個(gè)例子:浮點(diǎn)數(shù)的實(shí)現(xiàn)表明兩個(gè)非數(shù)字(NaN
,not-a-number)值是互不相等的。
例如,對(duì)于一個(gè) HashMap<K, V>
中的 key 來說, Eq
是必須的,這樣 HashMap<K, V>
就可以知道兩個(gè) key 是否一樣了。
PartialOrd
trait 可以基于排序的目的而比較一個(gè)類型的實(shí)例。實(shí)現(xiàn)了 PartialOrd
的類型可以使用 <
、 >
、<=
和 >=
操作符。但只能在同時(shí)實(shí)現(xiàn)了 PartialEq
的類型上使用 PartialOrd
。
派生 PartialOrd
實(shí)現(xiàn)了 partial_cmp
方法,其返回一個(gè) Option<Ordering>
,但當(dāng)給定值無法產(chǎn)生順序時(shí)將返回 None
。盡管大多數(shù)類型的值都可以比較,但一個(gè)無法產(chǎn)生順序的例子是:浮點(diǎn)類型的非數(shù)字值。當(dāng)在浮點(diǎn)數(shù)上調(diào)用 partial_cmp
時(shí),NaN
的浮點(diǎn)數(shù)將返回 None
。
當(dāng)在結(jié)構(gòu)體上派生時(shí),PartialOrd
以在結(jié)構(gòu)體定義中字段出現(xiàn)的順序比較每個(gè)字段的值來比較兩個(gè)實(shí)例。當(dāng)在枚舉上派生時(shí),認(rèn)為在枚舉定義中聲明較早的枚舉變體小于其后的變體。
例如,對(duì)于來自于 rand
crate 中的 gen_range
方法來說,當(dāng)在一個(gè)范圍表達(dá)式指定的范圍內(nèi)生成一個(gè)隨機(jī)值時(shí),PartialOrd
trait 是必須的。
Ord
trait 也讓你明白在一個(gè)帶注解類型上的任意兩個(gè)值存在有效順序。Ord
trait 實(shí)現(xiàn)了 cmp
方法,它返回一個(gè) Ordering
而不是 Option<Ordering>
,因?yàn)榭偞嬖谝粋€(gè)合法的順序。只可以在實(shí)現(xiàn)了 PartialOrd
和 Eq
(Eq
依賴 PartialEq
)的類型上使用 Ord
trait 。當(dāng)在結(jié)構(gòu)體或枚舉上派生時(shí), cmp
和以 PartialOrd
派生實(shí)現(xiàn)的 partial_cmp
表現(xiàn)一致。
例如,當(dāng)在 BTreeSet<T>
(一種基于有序值存儲(chǔ)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu))上存值時(shí),Ord
是必須的。
Clone
trait 可以明確地創(chuàng)建一個(gè)值的深拷貝(deep copy),復(fù)制過程可能包含任意代碼的執(zhí)行以及堆上數(shù)據(jù)的復(fù)制。查閱第四章 “變量與數(shù)據(jù)交互的方式(二):克隆” 以獲取有關(guān) Clone
的更多信息。
派生 Clone
實(shí)現(xiàn)了 clone
方法,其為整個(gè)的類型實(shí)現(xiàn)時(shí),在類型的每一部分上調(diào)用了 clone
方法。這意味著類型中所有字段或值也必須實(shí)現(xiàn)了 Clone
,這樣才能夠派生 Clone
。
例如,當(dāng)在一個(gè)切片(slice)上調(diào)用 to_vec
方法時(shí),Clone
是必須的。切片并不擁有其所包含實(shí)例的類型,但是從 to_vec
中返回的 vector 需要擁有其實(shí)例,因此,to_vec
在每個(gè)元素上調(diào)用 clone
。因此,存儲(chǔ)在切片中的類型必須實(shí)現(xiàn) Clone
。
Copy
trait 允許你通過只拷貝存儲(chǔ)在棧上的位來復(fù)制值而不需要額外的代碼。查閱第四章 “只在棧上的數(shù)據(jù):拷貝” 的部分來獲取有關(guān) Copy
的更多信息。
Copy
trait 并未定義任何方法來阻止編程人員重寫這些方法或違反不需要執(zhí)行額外代碼的假設(shè)。盡管如此,所有的編程人員可以假設(shè)復(fù)制(copy)一個(gè)值非常快。
可以在類型內(nèi)部全部實(shí)現(xiàn) Copy
trait 的任意類型上派生 Copy
。一個(gè)實(shí)現(xiàn)了 Copy
的類型必須也實(shí)現(xiàn)了 Clone
,因?yàn)橐粋€(gè)實(shí)現(xiàn)了 Copy
的類型也簡單地實(shí)現(xiàn)了 Clone
,其執(zhí)行和 Copy
相同的任務(wù)。
Copy
trait 很少使用;實(shí)現(xiàn) Copy
的類型是可以優(yōu)化的,這意味著你無需調(diào)用 clone
,這讓代碼更簡潔。
任何使用 Copy
的代碼都可以通過 Clone
實(shí)現(xiàn),但代碼可能會(huì)稍慢,或者不得不在代碼中的許多位置上使用 clone
。
Hash
trait 可以實(shí)例化一個(gè)任意大小的類型,并且能夠用哈希(hash)函數(shù)將該實(shí)例映射到一個(gè)固定大小的值上。派生 Hash
實(shí)現(xiàn)了 hash
方法。hash
方法的派生實(shí)現(xiàn)結(jié)合了在類型的每部分調(diào)用 hash
的結(jié)果,這意味著所有的字段或值也必須實(shí)現(xiàn)了 Hash
,這樣才能夠派生 Hash
。
例如,在 HashMap<K, V>
上存儲(chǔ)數(shù)據(jù),存放 key 的時(shí)候,Hash
是必須的。
Default
trait 使你創(chuàng)建一個(gè)類型的默認(rèn)值。 派生 Default
實(shí)現(xiàn)了 default
函數(shù)。default
函數(shù)的派生實(shí)現(xiàn)調(diào)用了類型每部分的 default
函數(shù),這意味著類型中所有的字段或值也必須實(shí)現(xiàn)了 Default
,這樣才能夠派生 Default
。
Default::default
函數(shù)通常結(jié)合結(jié)構(gòu)體更新語法一起使用,這在第五章的 “使用結(jié)構(gòu)體更新語法從其他實(shí)例中創(chuàng)建實(shí)例” 部分有討論??梢宰远x一個(gè)結(jié)構(gòu)體的一小部分字段而剩余字段則使用 ..Default::default()
設(shè)置為默認(rèn)值。
例如,當(dāng)你在 Option<T>
實(shí)例上使用 unwrap_or_default
方法時(shí),Default
trait 是必須的。如果 Option<T>
是 None
的話, unwrap_or_default
方法將返回存儲(chǔ)在 Option<T>
中 T
類型的 Default::default
的結(jié)果。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: