Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

التعدادات مع البيانات

جزء من قسم 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 أشكال البيانات المختلفة تحت نوع واحد مع الحفاظ على المعلومات المحددة التي يحتاجها كل متغير.

challenge icon

التحدي

سهل

لنقم ببناء نظام إشعارات يستخدم التعدادات (enums) مع البيانات لتمثيل أنواع مختلفة من التنبيهات. يحمل كل نوع إشعار معلومات مختلفة—بعضها يحتوي على رسائل، وبعضها يحتوي على قيم رقمية، وبعضها عبارة عن إشارات بسيطة.

ستقوم بإنشاء ملفين لتنظيم الكود الخاص بك:

  • notification.rs: قم بتعريف Notification enum عام بثلاثة متغيرات (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: طباعة كل إشعار باستخدام تنسيق التصحيح {:?}
    // يجب طباعة كل إشعار في سطر خاص به
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming