كائنات السمات وdyn
الإرسال الديناميكي
كائنات السمات وdyn درس مجاني في Learn Rust Coding على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Learn Rust Coding، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Learn Rust Coding 4 دروس في المجموع.
المشكلة: أنواع مختلطة
تعمل الأنواع العامة مع حدود السمات جيدًا عندما يستخدم كل استدعاء نوعًا فعليًا واحدًا. لكن ماذا لو أردت مجموعة من أنواع مختلفة تشترك جميعها في سمة؟ لا تستطيع الأنواع العامة احتواء مزيج من الأنواع.
تحل كائنات السمات هذه المشكلة.
ما هو كائن السمة؟
كائن السمة هو قيمة يُشار إليها عبر مؤشر بالإضافة إلى الكلمة المفتاحية dyn، مثل &dyn Trait أو Box<dyn Trait>.
ويتيح لك التعامل مع أنواع فعلية عديدة بطريقة موحّدة أثناء التشغيل.
صندوق من dyn Trait
يمتلك Box<dyn Trait> قيمة على الكومة من نوع ما ينفذ السمة. ويمكنك استدعاء دوال السمة دون معرفة النوع الفعلي.
trait Speak { fn say(&self) -> String; }
struct Dog;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
fn main() {
let animal: Box<dyn Speak> = Box::new(Dog);
println!("{}", animal.say());
}متجه من كائنات السمات
الفائدة الكبرى هي أن متجهًا واحدًا يمكنه احتواء أنواع مختلفة عديدة، ما دام كل نوع منها ينفذ السمة.
trait Speak { fn say(&self) -> String; }
struct Dog;
struct Cat;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
impl Speak for Cat { fn say(&self) -> String { String::from("Meow") } }
fn main() {
let zoo: Vec<Box<dyn Speak>> = vec![Box::new(Dog), Box::new(Cat)];
for animal in &zoo {
println!("{}", animal.say());
}
}التوزيع الديناميكي
مع كائنات السمات، يُختار الأسلوب الذي سيُستدعى أثناء التشغيل بالبحث عنه في جدول مخفي (جدول الدوال الافتراضية). ويُسمى ذلك التوزيع الديناميكي.
تكمن الكلفة في مستوى indirection صغير؛ أما الفائدة فهي المرونة أثناء التشغيل.
دوال تُرجع كائنات السمات
يمكن للدالة إرجاع Box<dyn Trait> عندما يختلف النوع الفعلي. ويفيد ذلك في دوال المصنع التي تقرر النوع أثناء التشغيل.
trait Speak { fn say(&self) -> String; }
struct Dog;
struct Cat;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
impl Speak for Cat { fn say(&self) -> String { String::from("Meow") } }
fn make(kind: &str) -> Box<dyn Speak> {
if kind == "dog" { Box::new(Dog) } else { Box::new(Cat) }
}
fn main() {
println!("{}", make("cat").say());
}كائنات السمات المستعارة
يمكنك أيضًا تمرير كائن سمة مستعار باستخدام &dyn Trait عندما لا تحتاج إلى الملكية. ولا يتضمن ذلك أي تخصيص على الكومة.
trait Speak { fn say(&self) -> String; }
struct Dog;
impl Speak for Dog { fn say(&self) -> String { String::from("Woof") } }
fn announce(s: &dyn Speak) {
println!("heard: {}", s.say());
}
fn main() {
let d = Dog;
announce(&d);
}أمان الكائنات
لا يمكن أن تصبح كل سمة كائن سمة. يجب أن تكون السمة آمنة للكائنات: وبصورة تقريبية، لا يجوز لدوالها إرجاع Self بالقيمة أو استخدام معاملات أنواع عامة.
أما الدوال التي تأخذ &self وتستخدم أنواعًا فعلية فهي صالحة.
مثال على سمة غير آمنة للكائنات
لا يمكن استخدام سمة تحتوي على دالة تُرجع Self كـ dyn، لأن حجم Self غير معروف خلف المؤشر. اجعل سمات كائنات السمات بسيطة.
مثال بأسلوب الإضافات
تتألق كائنات السمات في أنظمة الإضافات: خزّن قائمة من المعالجات خلف dyn وشغّلها كلها دون الاهتمام بالأنواع الفعلية.
trait Task { fn run(&self) -> i32; }
struct Add { a: i32, b: i32 }
struct Negate { x: i32 }
impl Task for Add { fn run(&self) -> i32 { self.a + self.b } }
impl Task for Negate { fn run(&self) -> i32 { -self.x } }
fn main() {
let tasks: Vec<Box<dyn Task>> = vec![Box::new(Add { a: 2, b: 3 }), Box::new(Negate { x: 7 })];
let total: i32 = tasks.iter().map(|t| t.run()).sum();
println!("total {}", total);
}متى تستخدم dyn؟
استخدم كائنات السمات عندما تحتاج إلى مجموعات متغايرة، أو أنواع يتم اختيارها أثناء التشغيل، أو تريد تقليل تضخم الشيفرة الناتج عن إنشاء العديد من النسخ المتخصصة للأنواع العامة.
وإلا ففضّل الأنواع العامة لتحقيق أقصى سرعة.
تحقق سريع
اختبر مدى فهمك لكائنات السمات.
مراجعة
لقد تعلمت التوزيع الديناميكي:
- تستخدم كائنات السمات
dynخلف مؤشر (Box<dyn T>و&dyn T) - تتيح مجموعات متغايرة وأنواعًا يتم اختيارها أثناء التشغيل
- تمر استدعاءات الدوال عبر جدول الدوال الافتراضية (التوزيع الديناميكي)
- يجب أن تكون السمات آمنة للكائنات لاستخدامها بهذه الطريقة
الأسئلة الشائعة
هل درس «كائنات السمات وdyn» مجاني؟
نعم — نص درس «كائنات السمات وdyn» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Learn Rust Coding، انتقل إلى CoddyKit PRO. تتضمن دورة Learn Rust Coding 4 دروس في المجموع.
ماذا ستتعلم في «كائنات السمات وdyn»؟
الإرسال الديناميكي تتمرن على Learn Rust Coding مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Learn Rust Coding؟
لا تُشترط خبرة سابقة. Learn Rust Coding على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «كائنات السمات وdyn»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Learn Rust Coding هذا؟
نعم. كل درس في Learn Rust Coding يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- تعريف السمات
- كائنات السمات وdyn
- الإرسال الساكن مقابل الديناميكي
- الأساليب الافتراضية