الأساليب (Methods) في التعدادات
جزء من قسم Object Oriented Programming في رحلة Rust على Coddy — الدرس 15 من 61.
تماماً مثل الـ structs، يمكن أن تحتوي الـ enums على methods مُعرفة في كتل impl. يتيح لك هذا إرفاق سلوك مباشرة بنوع الـ enum الخاص بك، مما يسهل العمل مع الـ variants المختلفة من خلال واجهة موحدة.
إليك كيفية إضافة method إلى التعداد Message من الدرس السابق:
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
}
impl Message {
fn describe(&self) -> String {
match self {
Message::Quit => String::from("Quit signal"),
Message::Move { x, y } => format!("Move to ({}, {})", x, y),
Message::Write(text) => format!("Message: {}", text),
}
}
}
تعمل كتلة impl Message تماماً كما تعمل مع الـ structs. تأخذ الطريقة &self للوصول إلى مثيل الـ enum. داخل الطريقة، تستخدم match لتحديد الـ variant الذي تتعامل معه وإرجاع النتيجة المناسبة.
يبدو استدعاء الطريقة كما هو بغض النظر عن المتغير (variant) الذي تملكه:
fn main() {
let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
println!("{}", m1.describe()); // إشارة الخروج
println!("{}", m2.describe()); // الانتقال إلى (10, 20)
}
هذا النمط قوي لأن المستدعي لا يحتاج إلى معرفة أي نوع (variant) لديه—فهو يكتفي باستدعاء الطريقة (method)، ويتولى التعداد (enum) الباقي داخلياً. يتغير السلوك بناءً على النوع (variant)، لكن الواجهة (interface) تظل ثابتة.
التحدي
سهللنقم ببناء نظام إشارات مرور يستخدم enum مع دوال (methods) لوصف حالة الإشارة الحالية. سيحمل كل لون إشارة معلومات حول مدة استمراره، وستوفر دالة وصفاً قابلاً للقراءة من قبل البشر.
ستقوم بإنشاء ملفين لتنظيم الكود الخاص بك:
traffic.rs: قم بتعريف enum عام باسمTrafficLightمع ثلاثة متغيرات (variants):Red— يحمل قيمةu32تمثل ثواني الانتظارYellow— يحمل قيمةu32تمثل ثواني الانتظارGreen— يحمل قيمةu32تمثل ثواني الانطلاق
statusتعيدStringيصف الإشارة. استخدمmatchداخل الدالة للتعامل مع كل متغير وتضمين المدة في الرسالة.main.rs: قم باستيراد وحدة المرور (traffic module) الخاصة بك، وأنشئ مثيلات (instances) لكل متغير من متغيرات الإشارة، واستدعِ دالةstatusعلى كل منها لطباعة الأوصاف.
يجب أن تعيد دالة status رسائل بهذه التنسيقات الدقيقة:
- لـ
Red:Stop for {seconds} seconds - لـ
Yellow:Caution for {seconds} seconds - لـ
Green:Go for {seconds} seconds
يجب أن يعرض مخرجك حالة كل إشارة في سطر مستقل:
Stop for {seconds} seconds
Caution for {seconds} seconds
Go for {seconds} secondsعلى سبيل المثال، مع إشارة حمراء مدتها 30 ثانية، وصفراء مدتها 5 ثوانٍ، وخضراء مدتها 25 ثانية، سيكون المخرج:
Stop for 30 seconds
Caution for 5 seconds
Go for 25 secondsستتلقى ثلاثة مدخلات: مدة الإشارة الحمراء، ومدة الإشارة الصفراء، ومدة الإشارة الخضراء.
ورقة مرجعية
يمكن أن تحتوي التعدادات (Enums) على دوال (methods) معرفة في كتل impl، تماماً مثل الهياكل (structs):
enum Message {
Quit,
Move { x: i32, y: i32 },
Write(String),
}
impl Message {
fn describe(&self) -> String {
match self {
Message::Quit => String::from("Quit signal"),
Message::Move { x, y } => format!("Move to ({}, {})", x, y),
Message::Write(text) => format!("Message: {}", text),
}
}
}
تأخذ الدوال &self للوصول إلى مثيل التعداد واستخدام match للتعامل مع المتغيرات (variants) المختلفة:
let m1 = Message::Quit;
let m2 = Message::Move { x: 10, y: 20 };
println!("{}", m1.describe()); // إشارة الخروج
println!("{}", m2.describe()); // الانتقال إلى (10, 20)
يستخدم المستدعي نفس الواجهة بغض النظر عن المتغير (variant) - حيث يتعامل التعداد مع السلوك داخلياً بناءً على نوع المتغير.
جرّب بنفسك
mod traffic;
use traffic::TrafficLight;
fn main() {
// قراءة المدخلات للمدد الزمنية
let mut red_input = String::new();
std::io::stdin().read_line(&mut red_input).expect("Failed to read line");
let red_duration: u32 = red_input.trim().parse().expect("Invalid number");
let mut yellow_input = String::new();
std::io::stdin().read_line(&mut yellow_input).expect("Failed to read line");
let yellow_duration: u32 = yellow_input.trim().parse().expect("Invalid number");
let mut green_input = String::new();
std::io::stdin().read_line(&mut green_input).expect("Failed to read line");
let green_duration: u32 = green_input.trim().parse().expect("Invalid number");
// TODO: إنشاء مثيلات لكل نوع من TrafficLight مع المدد الزمنية المدخلة
// TODO: استدعاء طريقة status لكل ضوء وطباعة النتيجة
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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 مع المعاملاتملخص - مشغل الوسائط