0Pricing
Learn Rust Coding · บทเรียน

การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต

ข้อแลกเปลี่ยน

การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การกำหนดคุณลักษณะ
  2. ออบเจ็กต์คุณลักษณะและ dyn
  3. การเรียกใช้แบบสแตติกเทียบกับแบบพลวัต
  4. เมธอดเริ่มต้น
← กลับไปที่ Learn Rust Coding