Traits
การนิยาม Trait
หัวข้อที่มีชื่อว่า “การนิยาม Trait”Trait คือชุดของ method signature — และ method body ที่เป็น optional — ที่อธิบายความสามารถของ type ใดก็ตามที่สัญญาว่าจะจัดหา method เหล่านั้น ถือว่า implement trait นั้น
trait Greet { fn hello(&self) -> String;}นี่คือการประกาศ method ที่จำเป็นหนึ่งอย่าง struct ใดที่ต้องการเป็น Greet-able จะต้องจัดหา implementation ของ hello ที่เป็น concrete
การ Implement Trait
หัวข้อที่มีชื่อว่า “การ Implement Trait”ใช้ impl TraitName for TypeName เพื่อปฏิบัติตาม trait contract:
struct Dog { name: String,}
impl Greet for Dog { fn hello(&self) -> String { format!("Woof! I'm {}.", self.name) }}เมื่อ Dog implement Greet แล้ว คุณสามารถเรียก .hello() บน Dog value ใดก็ได้:
let d = Dog { name: String::from("Rex") };println!("{}", d.hello()); // Woof! I'm Rex.Default Methods
หัวข้อที่มีชื่อว่า “Default Methods”Trait สามารถจัดหา body เริ่มต้นสำหรับ method ใดก็ได้ ผู้ implement สามารถ override หรือใช้ค่าเริ่มต้นได้:
trait Shape { fn area(&self) -> f64;
// Default method — implementors get this for free fn describe(&self) -> String { format!("I am a shape with area {:.2}", self.area()) }}Circle และ Rectangle ต้อง implement แค่ area เท่านั้น Method describe จะถูกรับมาโดยอัตโนมัติและเรียก area ของ type นั้น ณ runtime
การเรียก Trait Methods
หัวข้อที่มีชื่อว่า “การเรียก Trait Methods”Trait method ถูกเรียกด้วย dot syntax ปกติ ตราบเท่าที่ trait อยู่ใน scope หาก trait หลายอันมี method ชื่อเดียวกัน คุณสามารถใช้ fully qualified syntax เพื่อแยกแยะ:
<Circle as Shape>::area(&c)ในทางปฏิบัติ dot syntax ใช้งานได้ในกรณีส่วนใหญ่
Traits เป็น Function Parameter
หัวข้อที่มีชื่อว่า “Traits เป็น Function Parameter”คุณสามารถรับ type ใดก็ตามที่ implement trait โดยใช้ impl TraitName ใน function parameter:
fn print_area(shape: &impl Shape) { println!("Area: {:.2}", shape.area());}นี่คือ shorthand สำหรับ generic function พร้อม trait bound ซึ่งคุณจะเรียนรู้เพิ่มเติมในบทเรียน Generics
ลองเล่น
หัวข้อที่มีชื่อว่า “ลองเล่น”Playground ด้านล่างนิยาม trait Shape พร้อม method area ที่ต้อง implement และ method describe แบบ default ทั้ง Circle และ Rectangle implement area และรับ describe มาฟรี
trait Shape { fn area(&self) -> f64; fn describe(&self) -> String { format!("I am a shape with area {:.2}", self.area()) }}
struct Circle { radius: f64 }struct Rectangle { width: f64, height: f64 }
impl Shape for Circle { fn area(&self) -> f64 { std::f64::consts::PI * self.radius * self.radius }}
impl Shape for Rectangle { fn area(&self) -> f64 { self.width * self.height }}
fn main() { let c = Circle { radius: 3.0 }; let r = Rectangle { width: 4.0, height: 5.0 };
println!("Circle area: {:.2}", c.area()); println!("{}", c.describe()); println!("Rectangle area: {:.2}", r.area()); println!("{}", r.describe());}Compiling…