ข้ามไปยังเนื้อหา

Generics

ลองนึกภาพว่าคุณต้องหาค่าที่ใหญ่ที่สุดใน slice สำหรับ integer คุณเขียน largest_i32 สำหรับ char คุณเขียน largest_char — body เหมือนกันทุกอย่างแต่ต่าง type Generics แก้ปัญหานี้โดยให้คุณใช้ type parameter แทน concrete type:

fn largest<T: PartialOrd>(list: &[T]) -> &T {
// ...
}

ตัว <T: PartialOrd> อ่านว่า “สำหรับ type ใดก็ตาม T ที่ implement PartialOrd” Trait bound PartialOrd บอก compiler ว่า T รองรับการเปรียบเทียบด้วย >

คุณสามารถทำให้ struct เป็น generic ได้เช่นกัน ทำให้ field ทำงานกับ type ใดก็ได้:

struct Pair<T> {
first: T,
second: T,
}

Pair<i32> เก็บ integer สองอัน Pair<String> เก็บ String สองอัน เป็นต้น

เมื่อคุณต้องการ implement method สำหรับ generic struct ด้วย constraint บางอย่าง:

impl<T: std::fmt::Display + PartialOrd> Pair<T> {
fn larger(&self) -> &T {
if self.first > self.second { &self.first } else { &self.second }
}
}

T: Display + PartialOrd บอกว่า method larger มีให้เฉพาะ Pair<T> ที่ T รองรับทั้ง formatting และการเปรียบเทียบ

เมื่อ trait bound ยาวหรือซับซ้อน คุณสามารถย้ายไปไว้ใน where clause เพื่อให้อ่านง่ายขึ้น:

fn notify<T>(item: &T)
where
T: std::fmt::Display + Clone,
{
println!("{}", item);
}

ทั้งสอง syntax ทำงานเหมือนกันทุกประการ — where เป็นแค่ทางเลือกที่อ่านง่ายกว่าสำหรับ bound ที่ซับซ้อน

Playground ด้านล่างแสดง largest function แบบ generic, struct Pair<T> และ method ที่มี compound trait bound

fn largest<T: PartialOrd>(list: &[T]) -> &T {
let mut biggest = &list[0];
for item in list {
if item > biggest {
biggest = item;
}
}
biggest
}
struct Pair<T> {
first: T,
second: T,
}
impl<T: std::fmt::Display + PartialOrd> Pair<T> {
fn new(first: T, second: T) -> Self {
Self { first, second }
}
fn larger(&self) -> &T {
if self.first > self.second {
&self.first
} else {
&self.second
}
}
}
fn main() {
let numbers = vec![34, 50, 25, 100, 65];
println!("largest number: {}", largest(&numbers));
let chars = vec!['y', 'm', 'a', 'q'];
println!("largest char: {}", largest(&chars));
let p = Pair::new(5, 10);
println!("larger of pair: {}", p.larger());
}
`T: PartialOrd` ใน `fn largest<T: PartialOrd>(...)` หมายความว่าอะไร?
monomorphization คืออะไร?
จะประกาศ generic struct `Stack` ที่เก็บ element ของ type `T` อย่างไร?
จุดประสงค์ของ `where` clause ใน generic function คืออะไร?