Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ภาคผนวก 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>