تجاوز التنفيذات الافتراضية
جزء من قسم البرمجة كائنية التوجه في رحلة Rust على Coddy. الدرس 32 من 61.
تطبيقات default مريحة، لكن أحيانًا يحتاج نوعٌ ما إلى سلوك يختلف عن السلوك القياسي. عند حدوث ذلك، يمكنك override التطبيق الافتراضي من خلال توفير تطبيقك الخاص في كتلة impl.
ما عليك سوى تعريف method بالتوقيع نفسه، ولكن مع تضمين منطقك المخصص:
trait Greet {
fn greet(&self) -> String {
String::from("Hello there!")
}
}
struct Robot {
id: u32,
}
impl Greet for Robot {
fn greet(&self) -> String {
format!("BEEP BOOP. Unit {} online.", self.id)
}
}
على الرغم من أن Greet يوفر method افتراضيًا باسم greet، فإن Robot يستبدله بالكامل بإصدار خاص به. عند استدعاء greet() على كائن من نوع Robot، تستخدم Rust الـ implementation المخصص:
let bot = Robot { id: 42 };
println!("{}", bot.greet()); // BEEP BOOP. الوحدة 42 متصلة.
يمنحك هذا مرونة: فالأنواع التي تكون راضية عن default لا تحتاج إلى كتابة أي شيء، بينما يمكن للأنواع التي تحتاج إلى سلوك متخصص أن تتجاوز فقط method التي تهتم بها. وتظل السمة تضمن أن كل نوع مُطبِّق يملك method متاحة.
التحدي
سهللنبنِ نظام إشعارات يمكن فيه لأنواع التنبيهات المختلفة تخصيص رسائلها! ستنشئ trait مع implementation افتراضية، ثم تجعل نوعًا واحدًا يستخدم الإعداد الافتراضي بينما يتجاوز نوع آخر ذلك بسلوك مخصص.
ستنظم كودك عبر ثلاثة ملفات:
notifiable.rs: عرّف trait عامة باسمNotifiableمعmethodباسمnotify(&self) -> Stringلهاimplementationافتراضية تُرجع"Alert: Something happened!".alerts.rs: أنشئ بنيتين عامتين تطبّقان trait بطرق مختلفة:GenericAlert: بنية unit تستخدم الإشعار الافتراضي (كتلةimplفارغة)UrgentAlert: بنية تحتوي علىfieldعامة باسمmessageمن النوع (String) وتقوم بعملoverrideللإعداد الافتراضي لإرجاع"URGENT: {message}"حيث إن{message}هي رسالتها المخزنة
main.rs: اجمع الوحدات معًا واعرض السلوكين. أنشئGenericAlertوUrgentAlertباستخدامinputالمقدّم، ثم اطبع إشعاراتهما.
الفكرة الأساسية هنا هي أن GenericAlert يحصل على سلوك مجاني من الإعداد الافتراضي، بينما يوفّر UrgentAlert نسخته المتخصصة من خلال تعريف method في كتلة impl الخاصة به.
يجب أن يتبع ناتجك هذا التنسيق:
Alert: Something happened!
URGENT: {message}على سبيل المثال، مع input هو Server is down!:
Alert: Something happened!
URGENT: Server is down!ستتلقى input واحدًا: الرسالة الخاصة بالتنبيه العاجل.
جرّب بنفسك
mod notifiable;
mod alerts;
use alerts::{GenericAlert, UrgentAlert};
use notifiable::Notifiable;
fn main() {
// اقرأ الإدخال لرسالة التنبيه العاجل
let mut input = String::new();
std::io::stdin().read_line(&mut input).expect("Failed to read line");
let message = input.trim().to_string();
// TODO: أنشئ مثيلاً من GenericAlert
// TODO: أنشئ مثيلاً من UrgentAlert مع رسالة الإدخال
// TODO: اطبع الإشعار من GenericAlert
// TODO: اطبع الإشعار من UrgentAlert
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس البرمجة كائنية التوجه
1الأساليب والسلوك
مقدمة في كتل التنفيذمعامل Selfالأساليب القابلة للتعديلالدوال المرتبطةكتل تنفيذ متعددةتسلسل الأساليبمراجعة - إجراءات المستطيل4مشروع: حيوان أليف افتراضي
تعريف الحيوان الأليفإطعام الحيوان الأليف2التغليف والوحدات البرمجية
أساسيات الوحدات البرمجيةالكلمة المفتاحية Publicالحقول الخاصةدوال Gettersدوال Settersمراجعة - الخزانة الآمنة5الأنواع العامة (Generics)
الـ Structs العامةالـ Methods العامةأنواع عامة متعددةالـ Functions العامةمراجعة - Coordinate Point3التعدادات المتقدمة (Advanced Enums)
التعدادات مع البياناتالأساليب (Methods) في التعداداتمطابقة حالات البياناتمراجعة التعداد Optionملخص - التعداد Shape6تعريف الـ Traits
ما هي الـ Trait؟تنفيذ الـ Traitsالتنفيذات الافتراضيةتجاوز التنفيذات الافتراضيةالـ Traits مع المعاملاتملخص - مشغل الوسائطتدرّب بنفسك: مترجم Rust عبر الإنترنت