ภาคผนวก C — Trait ที่ Derive ได้
ในที่ต่าง ๆ ในหนังสือ เราพูดถึง attribute derive ซึ่งคุณ apply ให้
นิยาม struct หรือ enum ได้ Attribute derive generate โค้ดที่จะ
implement trait กับ default implementation ของมันเองบน type ที่คุณ
annotate ด้วย syntax derive
ในภาคผนวกนี้ เราให้ reference ของ trait ทั้งหมดใน standard library
ที่คุณใช้กับ derive ได้ แต่ละส่วนครอบคลุม:
- Operator และเมธอดใดที่การ derive trait นี้จะเปิดใช้
- Implementation ของ trait ที่
deriveให้ทำอะไร - Implement trait หมายถึงอะไรเกี่ยวกับ type
- เงื่อนไขที่คุณได้รับอนุญาตหรือไม่ได้รับอนุญาตให้ implement trait
- ตัวอย่างของ operation ที่ต้องการ trait
ถ้าคุณต้องการพฤติกรรมต่างจากที่ attribute derive ให้ ปรึกษา standard
library documentation สำหรับแต่ละ
trait สำหรับรายละเอียดเกี่ยวกับวิธี implement พวกมันโดยมือ
Trait ที่ list ที่นี่เป็นอันเดียวที่นิยามโดย standard library ที่ถูก
implement บน type ของคุณโดยใช้ derive ได้ Trait อื่นที่นิยามใน
standard library ไม่มีพฤติกรรม default ที่สมเหตุสมผล ดังนั้นมันขึ้นกับ
คุณที่จะ implement พวกมันในวิธีที่สมเหตุสมผลสำหรับสิ่งที่คุณพยายาม
บรรลุ
ตัวอย่างของ trait ที่ derive ไม่ได้คือ Display ซึ่งจัดการการ format
สำหรับ user สุดท้าย คุณควรพิจารณาวิธีเหมาะสมในการแสดง type ให้ user
สุดท้ายเสมอ ส่วนใดของ type ที่ user สุดท้ายควรได้รับอนุญาตให้เห็น?
ส่วนใดที่พวกเขาจะพบเกี่ยวข้อง? Format ของข้อมูลใดจะเกี่ยวข้องที่สุด
กับพวกเขา? Compiler Rust ไม่มี insight นี้ ดังนั้นมันไม่สามารถให้
พฤติกรรม default เหมาะสมให้คุณ
list ของ trait ที่ derive ได้ที่ให้ในภาคผนวกนี้ไม่ครอบคลุม — library
implement derive สำหรับ trait ของพวกเขาเองได้ ทำให้ list ของ trait
ที่คุณใช้ derive ได้ open ended จริง ๆ Implement derive เกี่ยวข้อง
กับการใช้ procedural macro ซึ่งครอบคลุมในส่วน “Custom derive
Macro” ในบทที่ 20
Debug สำหรับ Output Programmer
Trait Debug เปิดใช้ debug formatting ใน format string ซึ่งคุณบ่ง
บอกโดยเพิ่ม :? ภายใน placeholder {}
Trait Debug อนุญาตให้คุณ print instance ของ type สำหรับจุดประสงค์
debug ดังนั้นคุณและ programmer อื่นที่ใช้ type ของคุณ inspect instance
ที่จุดเฉพาะในการ execute โปรแกรมได้
Trait Debug ถูกต้องการ ตัวอย่างเช่น ในการใช้ macro assert_eq!
Macro นี้ print ค่าของ instance ที่ให้เป็น argument ถ้า assertion
equality fail เพื่อให้ programmer เห็นว่าทำไมสอง instance ไม่เท่ากัน
PartialEq และ Eq สำหรับเปรียบเทียบ Equality
Trait PartialEq อนุญาตให้คุณเปรียบเทียบ instance ของ type เพื่อ
check equality และเปิดใช้การใช้ operator == และ !=
การ derive PartialEq implement เมธอด eq เมื่อ PartialEq ถูก
derive บน struct สอง instance เท่าเพียงถ้า ทุก field เท่า และ
instance ไม่เท่าถ้า ใด field ไม่เท่า เมื่อ derive บน enum, แต่ละ
variant เท่าตัวเองและไม่เท่ากับ variant อื่น
Trait PartialEq ถูกต้องการ ตัวอย่างเช่น กับการใช้ macro assert_eq!
ซึ่งต้องสามารถเปรียบเทียบสอง instance ของ type สำหรับ equality
Trait Eq ไม่มีเมธอด จุดประสงค์ของมันคือ signal ว่าสำหรับทุกค่าของ
type ที่ annotate ค่าเท่ากับตัวเอง Trait Eq apply ได้เพียงให้ type
ที่ implement PartialEq ด้วย แม้ไม่ทุก type ที่ implement
PartialEq implement Eq ได้ ตัวอย่างของนี้คือ type ตัวเลข
floating-point — implementation ของตัวเลข floating-point บอกว่าสอง
instance ของค่า not-a-number (NaN) ไม่เท่ากัน
ตัวอย่างของเมื่อ Eq ถูกต้องการคือสำหรับ key ใน HashMap<K, V> เพื่อ
ให้ HashMap<K, V> บอกได้ว่าสอง key เหมือนกัน
PartialOrd และ Ord สำหรับเปรียบเทียบ Ordering
Trait PartialOrd อนุญาตให้คุณเปรียบเทียบ instance ของ type สำหรับ
จุดประสงค์ sort type ที่ implement PartialOrd ใช้กับ operator <,
>, <= และ >= ได้ คุณ apply trait PartialOrd ได้เพียงให้ type
ที่ implement PartialEq ด้วย
การ derive PartialOrd implement เมธอด partial_cmp ซึ่ง return
Option<Ordering> ที่จะเป็น None เมื่อค่าที่ให้ไม่ผลิต ordering
ตัวอย่างของค่าที่ไม่ผลิต ordering แม้ค่าส่วนใหญ่ของ type นั้นถูก
เปรียบเทียบได้ คือค่า floating point NaN เรียก partial_cmp กับ
ตัวเลข floating-point ใดและค่า floating-point NaN จะ return None
เมื่อ derive บน struct, PartialOrd เปรียบเทียบสอง instance โดย
เปรียบเทียบค่าในแต่ละ field ในลำดับที่ field ปรากฏในนิยาม struct เมื่อ
derive บน enum, variant ของ enum ที่ประกาศก่อนหน้าในนิยาม enum ถูก
พิจารณาน้อยกว่า variant ที่ list ภายหลัง
Trait PartialOrd ถูกต้องการ ตัวอย่างเช่น สำหรับเมธอด gen_range
จาก crate rand ที่ generate ค่า random ใน range ที่ระบุโดย
expression range
Trait Ord อนุญาตให้คุณรู้ว่าสำหรับสองค่าใดของ type ที่ annotate
ordering valid จะมี Trait Ord implement เมธอด cmp ซึ่ง return
Ordering แทน Option<Ordering> เพราะ ordering valid จะเป็นไปได้
เสมอ คุณ apply trait Ord ได้เพียงให้ type ที่ implement
PartialOrd และ Eq ด้วย (และ Eq ต้องการ PartialEq) เมื่อ derive
บน struct และ enum, cmp ทำตัวในวิธีเดียวกับ implementation ที่
derive สำหรับ partial_cmp ทำกับ PartialOrd
ตัวอย่างของเมื่อ Ord ถูกต้องการคือเมื่อเก็บค่าใน BTreeSet<T> ซึ่ง
คือโครงสร้างข้อมูลที่เก็บข้อมูลตามลำดับ sort ของค่า
Clone และ Copy สำหรับ Duplicate ค่า
Trait Clone อนุญาตให้คุณสร้าง deep copy ของค่าอย่างชัดเจน และ
กระบวนการ duplicate อาจเกี่ยวข้องกับการรันโค้ดใด ๆ และ copy ข้อมูล
heap ดูส่วน “ตัวแปรและข้อมูล Interact กับ
Clone” ใน
บทที่ 4 สำหรับข้อมูลเพิ่มเติมเกี่ยวกับ Clone
การ derive Clone implement เมธอด clone ซึ่งเมื่อ implement สำหรับ
type ทั้งหมด เรียก clone บนแต่ละส่วนของ type นี่หมายความว่า field
หรือค่าทั้งหมดใน type ต้อง implement Clone ด้วยเพื่อ derive
Clone
ตัวอย่างของเมื่อ Clone ถูกต้องการคือเมื่อเรียกเมธอด to_vec บน
slice slice ไม่เป็นเจ้าของ instance type ที่มันบรรจุ แต่ vector ที่
return จาก to_vec จะต้องเป็นเจ้าของ instance ของมัน ดังนั้น to_vec
เรียก clone บนแต่ละ item ดังนั้น type ที่เก็บใน slice ต้อง
implement Clone
Trait Copy อนุญาตให้คุณ duplicate ค่าโดยเพียง copy bit ที่เก็บบน
stack — ไม่มีโค้ดใด ๆ จำเป็น ดูส่วน “ข้อมูล Stack-Only —
Copy” ในบทที่ 4 สำหรับข้อมูล
เพิ่มเติมเกี่ยวกับ Copy
Trait Copy ไม่นิยามเมธอดใดเพื่อป้องกัน programmer จากการ overload
เมธอดเหล่านั้นและละเมิดสมมติฐานว่าไม่มีโค้ดใด ๆ ถูกรัน ด้วยวิธีนั้น
programmer ทั้งหมดสมมุติได้ว่า copy ค่าจะเร็วมาก
คุณ derive Copy บน type ใดที่ส่วนทั้งหมดของมัน implement Copy ได้
type ที่ implement Copy ต้อง implement Clone ด้วยเพราะ type ที่
implement Copy มี implementation trivial ของ Clone ที่ทำงาน
เดียวกับ Copy
Trait Copy ถูกต้องการแทบไม่ — type ที่ implement Copy มี
optimization ใช้ได้ หมายความว่าคุณไม่ต้องเรียก clone ซึ่งทำให้โค้ด
กระชับมากขึ้น
ทุกอย่างที่เป็นไปได้กับ Copy คุณบรรลุกับ Clone ได้ด้วย แต่โค้ดอาจ
ช้ากว่าหรือต้องใช้ clone ในที่
Hash สำหรับ Map ค่าไปยังค่าของขนาดคงที่
Trait Hash อนุญาตให้คุณรับ instance ของ type ของขนาดใด ๆ และ map
instance นั้นไปยังค่าของขนาดคงที่โดยใช้ฟังก์ชัน hash การ derive Hash
implement เมธอด hash Implementation ที่ derive ของเมธอด hash
รวมผลของการเรียก hash บนแต่ละส่วนของ type หมายความว่า field หรือ
ค่าทั้งหมดต้อง implement Hash ด้วยเพื่อ derive Hash
ตัวอย่างของเมื่อ Hash ถูกต้องการคือในการเก็บ key ใน HashMap<K, V>
เพื่อเก็บข้อมูลอย่างมีประสิทธิภาพ
Default สำหรับค่า Default
Trait Default อนุญาตให้คุณสร้างค่า default สำหรับ type การ derive
Default implement ฟังก์ชัน default Implementation ที่ derive
ของฟังก์ชัน default เรียกฟังก์ชัน default บนแต่ละส่วนของ type
หมายความว่า field หรือค่าทั้งหมดใน type ต้อง implement Default
ด้วยเพื่อ derive Default
ฟังก์ชัน Default::default ถูกใช้ปกติร่วมกับ syntax update struct
ที่พูดถึงในส่วน “สร้าง Instance จาก Instance อื่นด้วย Syntax Update
Struct” ในบทที่ 5 คุณ customize ไม่กี่ field ของ struct และแล้วตั้ง
และใช้ค่า default สำหรับ field ที่เหลือโดยใช้ ..Default::default()
ได้
Trait Default ถูกต้องการเมื่อคุณใช้เมธอด unwrap_or_default บน
instance Option<T> ตัวอย่างเช่น ถ้า Option<T> คือ None เมธอด
unwrap_or_default จะ return ผลของ Default::default สำหรับ type
T ที่เก็บใน Option<T>