ขอบเขตของ trait
จำกัด泛型ด้วย trait
ขอบเขตของ trait เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
หน้าที่ของข้อจำกัด Trait
ข้อจำกัดของ trait จะจำกัดชนิดข้อมูลเจเนอริกให้เหลือเฉพาะชนิดที่ใช้ trait ที่กำหนดได้ โดยบอกคอมไพเลอร์ว่าชนิดข้อมูลนั้นรับรองพฤติกรรมใด
วิธีนี้ทำให้ใช้เมธอดของ trait ภายในโค้ดเจเนอริกได้ พร้อมทั้งยังคงใช้ฟังก์ชันกับชนิดข้อมูลได้หลายชนิด
ไวยากรณ์ข้อจำกัดแบบแทรกในบรรทัด
รูปแบบที่ง่ายที่สุดคือวางข้อจำกัดไว้ถัดจากพารามิเตอร์ชนิดข้อมูล: T: Trait ในที่นี้ T ต้องใช้ Display ได้ เพื่อให้พิมพ์ค่าได้
ภายในฟังก์ชัน ตอนนี้คุณสามารถเรียกใช้เมธอดใด ๆ ที่ Display มีให้
use std::fmt::Display;
fn show<T: Display>(value: T) {
println!("value = {}", value);
}Trait ที่กำหนดเอง
ข้อจำกัดใช้กับ trait ของคุณเองได้เช่นกัน กำหนด trait พร้อมเมธอด แล้วกำหนดให้ฟังก์ชันเจเนอริกมีข้อจำกัดเป็น trait นั้น
trait Summary นี้กำหนดให้ต้องมีเมธอด summarize ที่คืนค่าสตริง
trait Summary {
fn summarize(&self) -> String;
}การนำไปใช้และการกำหนดข้อจำกัด
นำ trait ไปใช้กับชนิดข้อมูลหนึ่ง จากนั้นฟังก์ชันที่มีข้อจำกัดจะรับชนิดข้อมูลใด ๆ ที่นำ trait นี้ไปใช้ได้ ฟังก์ชันจะเรียกเมธอดของ trait โดยไม่จำเป็นต้องรู้ชนิดข้อมูลจริง
โปรแกรมฉบับเต็มนี้พิมพ์บทสรุปของ Article
trait Summary { fn summarize(&self) -> String; }
struct Article { title: String }
impl Summary for Article {
fn summarize(&self) -> String {
format!("Article: {}", self.title)
}
}
fn notify<T: Summary>(item: &T) {
println!("{}", item.summarize());
}
fn main() {
let a = Article { title: String::from("Rust") };
notify(&a);
}การรวมข้อจำกัดด้วย +
กำหนดให้ต้องใช้หลาย trait พร้อมกันด้วยการเชื่อมด้วย + ในที่นี้ T ต้องใช้ทั้ง Display และ Clone ได้
จากนั้นฟังก์ชันจะพิมพ์ค่าและโคลนค่าได้ด้วย
use std::fmt::Display;
fn process<T: Display + Clone>(value: T) {
let copy = value.clone();
println!("{}", copy);
}impl Trait ในอาร์กิวเมนต์
ไวยากรณ์ impl Trait ในตำแหน่งอาร์กิวเมนต์เป็นรูปแบบย่อของข้อกำหนดอย่างง่าย item: &impl Summary มีความหมายเหมือนพารามิเตอร์แบบ <T: Summary>
รูปแบบนี้กระชับสำหรับกรณีที่มีอาร์กิวเมนต์เดียว แต่ควบคุมการนำชนิดไปใช้ซ้ำได้น้อยกว่า
trait Summary { fn summarize(&self) -> String; }
fn notify(item: &impl Summary) {
println!("{}", item.summarize());
}การคืนค่า impl Trait
คุณสามารถคืนค่า impl Trait เพื่อซ่อนชนิดที่เป็นรูปธรรม พร้อมรับรองว่าชนิดนั้นใช้งานเทรตดังกล่าวได้ วิธีนี้มีประโยชน์กับคลอเชอร์และตัววนซ้ำ
ผู้เรียกจะทราบเพียงว่าผลลัพธ์ใช้งานเทรตที่ระบุได้
fn make_adder(n: i32) -> impl Fn(i32) -> i32 {
move |x| x + n
}
fn main() {
let add5 = make_adder(5);
println!("{}", add5(10));
}ข้อกำหนดเปิดใช้ตัวดำเนินการ
ตัวดำเนินการจะสอดคล้องกับเทรต ได้แก่ + ต้องใช้ Add, == ต้องใช้ PartialEq และการเปรียบเทียบต้องใช้ PartialOrd การกำหนดขอบเขตด้วยเทรตเหล่านี้ทำให้โค้ดทั่วไปใช้ตัวดำเนินการได้
ในที่นี้ การหาผลรวมกำหนดให้ T ต้องใช้งาน Add กับตัวมันเองได้
use std::ops::Add;
fn sum<T: Add<Output = T>>(a: T, b: T) -> T {
a + b
}เมธอดเริ่มต้นของเทรต
เทรตสามารถจัดเตรียมตัวเมธอดเริ่มต้นได้ ผู้ใช้งานเทรตอาจเขียนทับเมธอดเหล่านั้น หรือใช้ค่าเริ่มต้นต่อไปก็ได้ เจเนอริกที่มีข้อกำหนดจะใช้เมธอดที่มีผลอยู่ในขณะนั้น
Summary นี้มี summarize เป็นค่าเริ่มต้น ซึ่งชนิดต่าง ๆ สามารถคงไว้ตามเดิมได้
trait Summary {
fn summarize(&self) -> String {
String::from("(no summary)")
}
}
struct Note;
impl Summary for Note {}การเรียกใช้แบบสแตติกเทียบกับแบบไดนามิก
ข้อกำหนดเทรตใช้การเรียกใช้แบบสแตติก โดยคอมไพเลอร์จะเลือกเมธอดที่แน่นอนในเวลาคอมไพล์ผ่านการสร้างโค้ดเฉพาะชนิด ตรงกันข้าม dyn Trait ใช้การเรียกใช้แบบไดนามิกผ่านตารางเสมือน
โดยทั่วไปข้อกำหนดจะทำงานเร็วกว่า ส่วน dyn แลกความเร็วกับไบนารีที่มีขนาดเล็กลงและความยืดหยุ่นขณะทำงาน
ข้อกำหนดบนโครงสร้างข้อมูลเจเนอริก
ข้อกำหนดเทรตไม่ได้จำกัดอยู่แค่ฟังก์ชัน คุณสามารถกำหนดข้อกำหนดขณะประกาศโครงสร้างข้อมูล เพื่อให้ทุกอินสแตนซ์ใช้งานเทรตนั้นได้
ในที่นี้ Sortable<T> ทุกตัวรับรองว่าสามารถเปรียบเทียบสมาชิกของตนได้
struct Sortable<T: PartialOrd> {
items: Vec<T>,
}ตรวจสอบความเข้าใจ
ทดสอบความเข้าใจของคุณเกี่ยวกับข้อกำหนดเทรต
สรุปทบทวน
ข้อกำหนดเทรตจำกัดชนิดเจเนอริก เพื่อให้คอมไพเลอร์อนุญาตให้ใช้เมธอดและตัวดำเนินการของเทรตนั้นได้ คุณสามารถรวมเทรตด้วย + และใช้ impl Trait เป็นรูปแบบย่อในอาร์กิวเมนต์หรือค่าที่คืนกลับ
ข้อกำหนดให้การเรียกใช้แบบสแตติกโดยไม่มีค่าใช้จ่ายเพิ่มเติม ต่างจากการเรียกใช้แบบไดนามิกของ dyn Trait
คำถามที่พบบ่อย
บทเรียน “ขอบเขตของ trait” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “ขอบเขตของ trait” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “ขอบเขตของ trait”
จำกัด泛型ด้วย trait คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “ขอบเขตของ trait” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม
ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ