التعدادات مع البيانات
جزء من قسم Object Oriented Programming في رحلة Rust على Coddy — الدرس 14 من 61.
تسمح لك التعدادات (enums) الأساسية في لغة Rust بتعريف نوع بمجموعة ثابتة من المتغيرات (variants)—مثل Direction::North أو Status::Active. لكن التعدادات في Rust أقوى بكثير من ذلك. يمكن لكل متغير أن يحمل بياناته الخاصة، مما يجعل التعدادات مرنة للغاية لنمذجة سيناريوهات العالم الحقيقي.
فكر في نظام مراسلة حيث تحمل أنواع الرسائل المختلفة معلومات مختلفة. تحتوي الرسالة النصية على محتوى، وأمر النقل يحتوي على إحداثيات، وإشارة الإنهاء لا تحتوي على شيء على الإطلاق. في لغة Rust، يمكنك تمثيل كل هذه الحالات باستخدام enum واحد:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
ChangeColor(u8, u8, u8),
}
لكل متغير شكل مختلف. Quit لا يحمل أي بيانات - إنه مجرد إشارة.
يستخدم Move بناء جملة يشبه الـ struct مع حقول مسماة. يحمل Write قيمة String واحدة باستخدام بناء جملة الـ tuple. يحمل ChangeColor ثلاث قيم تمثل مكونات RGB.
إنشاء مثيلات من هذه المتغيرات يبدو كالتالي:
let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("Hello"));
let m4 = Message::ChangeColor(255, 128, 0);
جمال هذا النهج هو أن m1، و m2، و m3، و m4 جميعها من نفس النوع: Message. يمكنك تخزينها في نفس المجموعة، أو تمريرها إلى نفس الدالة، أو إرجاع أي متغير من دالة واحدة. يوحد الـ enum أشكال البيانات المختلفة تحت نوع واحد مع الحفاظ على المعلومات المحددة التي يحتاجها كل متغير.
التحدي
سهللنقم ببناء نظام إشعارات يستخدم التعدادات (enums) مع البيانات لتمثيل أنواع مختلفة من التنبيهات. يحمل كل نوع إشعار معلومات مختلفة—بعضها يحتوي على رسائل، وبعضها يحتوي على قيم رقمية، وبعضها عبارة عن إشارات بسيطة.
ستقوم بإنشاء ملفين لتنظيم الكود الخاص بك:
notification.rs: قم بتعريفNotificationenum عام بثلاثة متغيرات (variants):Alert— يحمل رسالةStringواحدة (صيغة tuple)Reminder— يحمل حقولاً مسماة:title(String) وminutes(u32)Dismiss— لا يحمل أي بيانات، مجرد إشارة
main.rs: قم باستيراد وحدة الإشعارات الخاصة بك وأنشئ مثيلاً واحداً (instance) لكل متغير. ثم اطبع معلومات حول كل إشعار لتوضيح أن جميع المتغيرات الثلاثة هي من نفس النوع ولكنها تحمل بيانات مختلفة.
عند الطباعة، استخدم تنسيق التصحيح ({:?}) لعرض كل إشعار. ستحتاج إلى اشتقاق سمة Debug في التعداد الخاص بك حتى يمكن طباعته بهذه الطريقة.
يجب أن يظهر مخرجك جميع الإشعارات الثلاثة، كل منها في سطر خاص به:
Alert("{message}")
Reminder { title: "{title}", minutes: {minutes} }
Dismissعلى سبيل المثال، مع رسالة تنبيه "Server down"، وتذكير بعنوان "Meeting" و 30 دقيقة، سيكون المخرج:
Alert("Server down")
Reminder { title: "Meeting", minutes: 30 }
Dismissستتلقى ثلاثة مدخلات: رسالة التنبيه، وعنوان التذكير، ودقائق التذكير.
ورقة مرجعية
يمكن لمتغيرات الـ Enum في لغة Rust أن تحمل أنواعًا مختلفة من البيانات، مما يجعلها قوية لنمذجة سيناريوهات متنوعة تحت نوع واحد.
تعريف الـ Enums مع البيانات
يمكن أن يكون لكل متغير هيكل بيانات خاص به:
enum Message {
Quit, // لا توجد بيانات
Move { x: i32, y: i32 }, // حقول مسمى (تشبه الـ struct)
Write(String), // قيمة واحدة (صيغة tuple)
ChangeColor(u8, u8, u8), // قيم متعددة (صيغة tuple)
}
إنشاء مثيلات الـ Enum
let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
let m3 = Message::Write(String::from("Hello"));
let m4 = Message::ChangeColor(255, 128, 0);
تعتبر جميع المثيلات من نفس النوع (Message) على الرغم من حملها لبيانات مختلفة، مما يسمح بتخزينها في المجموعات، أو تمريرها إلى الدوال، أو إرجاعها من الدوال بشكل موحد.
سمة Debug
لطباعة الـ enums باستخدام تنسيق {:?}، قم باشتقاق سمة Debug:
#[derive(Debug)]
enum Message {
// المتغيرات...
}
جرّب بنفسك
mod notification;
use notification::Notification;
fn main() {
// قراءة المدخلات
let mut alert_message = String::new();
std::io::stdin().read_line(&mut alert_message).expect("Failed to read line");
let alert_message = alert_message.trim().to_string();
let mut reminder_title = String::new();
std::io::stdin().read_line(&mut reminder_title).expect("Failed to read line");
let reminder_title = reminder_title.trim().to_string();
let mut minutes_input = String::new();
std::io::stdin().read_line(&mut minutes_input).expect("Failed to read line");
let reminder_minutes: u32 = minutes_input.trim().parse().expect("Failed to parse minutes");
// TODO: إنشاء إشعار Alert باستخدام alert_message
// TODO: إنشاء إشعار Reminder باستخدام reminder_title و reminder_minutes
// TODO: إنشاء إشعار Dismiss
// TODO: طباعة كل إشعار باستخدام تنسيق التصحيح {:?}
// يجب طباعة كل إشعار في سطر خاص به
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
1الأساليب والسلوك
مقدمة في كتل التنفيذمعامل Selfالأساليب القابلة للتعديلالدوال المرتبطةكتل تنفيذ متعددةتسلسل الأساليبمراجعة - إجراءات المستطيل4مشروع: حيوان أليف افتراضي
تعريف الحيوان الأليفإطعام الحيوان الأليف2التغليف والوحدات البرمجية
أساسيات الوحدات البرمجيةالكلمة المفتاحية Publicالحقول الخاصةدوال Gettersدوال Settersمراجعة - الخزانة الآمنة5الأنواع العامة (Generics)
الـ Structs العامةالـ Methods العامةأنواع عامة متعددةالـ Functions العامةمراجعة - Coordinate Point3التعدادات المتقدمة (Advanced Enums)
التعدادات مع البياناتالأساليب (Methods) في التعداداتمطابقة حالات البياناتمراجعة التعداد Optionملخص - التعداد Shape6تعريف الـ Traits
ما هي الـ Trait؟تنفيذ الـ Traitsالتنفيذات الافتراضيةتجاوز التنفيذات الافتراضيةالـ Traits مع المعاملاتملخص - مشغل الوسائط