การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต
ข้อแลกเปลี่ยน
การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต เป็นบทเรียน Learn Rust Coding ฟรีบน CoddyKit นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Learn Rust Coding และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
สองวิธีในการเรียกใช้
เมื่อคุณเรียกใช้เมธอดของเทรต Rust ต้องตัดสินใจว่าจะเรียกใช้การทำงานรูปธรรมใด โดยมีกลยุทธ์สองแบบ ได้แก่ การเรียกใช้แบบสแตติก (ตัดสินใจขณะคอมไพล์) และ การเรียกใช้แบบไดนามิก (ตัดสินใจขณะรันไทม์)
การเรียกใช้แบบสแตติกด้วยเจเนอริก
ฟังก์ชันแบบเจเนอริกใช้การเรียกใช้แบบสแตติก คอมไพเลอร์จะสร้างสำเนาเฉพาะสำหรับชนิดรูปธรรมแต่ละชนิด ซึ่งเป็นกระบวนการที่เรียกว่า การทำให้เป็นชนิดเดียว
trait Area { fn area(&self) -> f64; }
struct Square { s: f64 }
impl Area for Square { fn area(&self) -> f64 { self.s * self.s } }
fn print_area<T: Area>(shape: &T) {
println!("{}", shape.area());
}
fn main() {
print_area(&Square { s: 4.0 });
}การทำให้เป็นชนิดเดียว
สำหรับแต่ละชนิดที่คุณเรียกใช้ด้วย คอมไพเลอร์จะสร้างฟังก์ชันเวอร์ชันเฉพาะขึ้นมา การเรียกเมธอดจะกลายเป็นการเรียกโดยตรงโดยไม่ต้องค้นหา จึงทำงานได้เร็วพอ ๆ กับโค้ดที่เขียนด้วยมือ
การเรียกใช้แบบไดนามิกด้วย dyn
ออบเจ็กต์ของเทรตใช้การเรียกใช้แบบไดนามิก ฟังก์ชันเดียวรองรับทุกชนิด และที่อยู่ของเมธอดจะถูกค้นหาขณะรันไทม์ผ่านตารางเมธอดเสมือน
trait Area { fn area(&self) -> f64; }
struct Square { s: f64 }
impl Area for Square { fn area(&self) -> f64 { self.s * self.s } }
fn print_area(shape: &dyn Area) {
println!("{}", shape.area());
}
fn main() {
print_area(&Square { s: 4.0 });
}ตารางเมธอดเสมือน
ออบเจ็กต์ของเทรตคือตัวชี้แบบสองส่วน: ส่วนหนึ่งชี้ไปยังข้อมูล อีกส่วนชี้ไปยัง ตารางเมธอดเสมือน ที่แสดงรายการที่อยู่ของเมธอด การเรียกแต่ละครั้งจะใช้ดัชนีค้นหาในตารางนี้
การอ้อมผ่านตัวชี้เพิ่มเติมนี้คือต้นทุนขณะรันไทม์
การแลกเปลี่ยนด้านความเร็ว
การเรียกใช้แบบสแตติกเร็วกว่าเมื่อเรียกแต่ละครั้งและสามารถแทรกโค้ดได้ แต่จะสร้างโค้ดเครื่องมากกว่า การเรียกใช้แบบไดนามิกเพิ่มการอ้อมผ่านตัวชี้เพียงเล็กน้อย แต่ช่วยให้ขนาดโค้ดเล็ก
สำหรับแอปส่วนใหญ่ ความแตกต่างนี้แทบไม่มีนัยสำคัญ ให้เลือกตามความยืดหยุ่น
การแลกเปลี่ยนด้านขนาดโค้ด
การเรียกฟังก์ชันแบบเจเนอริกด้วยหลายชนิดจะสร้างสำเนาจำนวนมาก ซึ่งอาจทำให้ไบนารีมีขนาดใหญ่ขึ้น ฟังก์ชัน dyn เพียงฟังก์ชันเดียวช่วยหลีกเลี่ยงการทำซ้ำนี้
ด้วยเหตุนี้ ไลบรารีจึงมักเลือกใช้ออบเจ็กต์ของเทรตภายใน
การแลกเปลี่ยนด้านความยืดหยุ่น
เจเนอริกบังคับให้แต่ละจุดเรียกใช้มีชนิดรูปธรรมเพียงชนิดเดียว จึงไม่สามารถเก็บชนิดที่แตกต่างกันปะปนในคอลเลกชันได้ แต่ออบเจ็กต์ของเทรตทำได้ หากคุณต้องการรายการที่มีหลายชนิด การเรียกใช้แบบไดนามิกคือคำตอบ
trait Area { fn area(&self) -> f64; }
struct Square { s: f64 }
struct Rect { w: f64, h: f64 }
impl Area for Square { fn area(&self) -> f64 { self.s * self.s } }
impl Area for Rect { fn area(&self) -> f64 { self.w * self.h } }
fn main() {
let shapes: Vec<Box<dyn Area>> = vec![Box::new(Square { s: 2.0 }), Box::new(Rect { w: 3.0, h: 4.0 })];
let total: f64 = shapes.iter().map(|s| s.area()).sum();
println!("{}", total);
}การใช้ทั้งสองแบบร่วมกัน
คุณสามารถใช้ทั้งสองแบบร่วมกันได้: ฟังก์ชันแบบเจเนอริกอาจรับ impl Trait ที่ขอบเขตภายนอก แล้วเก็บค่าเป็น Box<dyn Trait> ภายใน ควรเลือกใช้แต่ละแบบให้เหมาะกับงาน
แนวทางช่วยตัดสินใจ
กฎง่าย ๆ:
- มีชนิดเดียวต่อการเรียกใช้ และอยู่ในเส้นทางที่ถูกเรียกบ่อยใช่หรือไม่ ใช้เจเนอริก (แบบสแตติก)
- มีชนิดปะปนกันในคอลเลกชันใช่หรือไม่ ใช้
dyn(แบบไดนามิก) - กังวลเรื่องขนาดไบนารีใช่หรือไม่ เอนเอียงไปทาง
dyn
ทั้งสองแบบไม่มีต้นทุนเพิ่มเติมในจุดสำคัญ
Rust ไม่เพิ่มภาระที่คุณไม่ได้ร้องขอ เจเนอริกไม่มีต้นทุนขณะรันไทม์ ส่วนออบเจ็กต์ของเทรตมีต้นทุนเพียงการอ้อมผ่านตัวชี้หนึ่งครั้ง คุณเป็นผู้เลือกการแลกเปลี่ยนนี้อย่างชัดเจน
ตรวจสอบความเข้าใจอย่างรวดเร็ว
ทดสอบความรู้ของคุณเกี่ยวกับการเรียกใช้
สรุปทบทวน
คุณได้เปรียบเทียบรูปแบบการเรียกใช้ทั้งสองแบบ:
- แบบสแตติก (เจเนอริก): ทำให้เป็นชนิดเดียว เร็ว ไบนารีใหญ่กว่า และมีชนิดเดียวต่อการเรียกใช้
- แบบไดนามิก (
dyn): ค้นหาผ่านตารางเมธอดเสมือน ยืดหยุ่น โค้ดเล็กกว่า และรองรับคอลเลกชันที่มีชนิดปะปนกัน - เลือกตามความต้องการด้านความยืดหยุ่น ประสิทธิภาพ และขนาดไบนารี
คำถามที่พบบ่อย
บทเรียน “การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Learn Rust Coding ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Learn Rust Coding มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต”
ข้อแลกเปลี่ยน คุณปฏิบัติ Learn Rust Coding ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Learn Rust Coding หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Learn Rust Coding บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 3 จากทั้งหมด 4 บทเรียน
บทเรียน “การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Learn Rust Coding นี้ได้ไหม
ได้ บทเรียน Learn Rust Coding ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การกำหนดคุณลักษณะ
- ออบเจ็กต์คุณลักษณะและ dyn
- การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต
- เมธอดเริ่มต้น