الرئيسية قاعدة المعرفة البرمجة والمنطق الهياكل والتعدادات في Rust: نمذجة بيانات المصنع
البرمجة والمنطق

الهياكل والتعدادات في Rust: نمذجة بيانات المصنع

الهياكل: أنواع بيانات مخصصة

الهياكل (Structs) تتيح لك تجميع بيانات مرتبطة في نوع واحد ذي معنى. بدلاً من تمرير عشرات المتغيرات المنفصلة، تُنشئ نوعاً يصف الكيان بالكامل.

// تعريف هيكل لمستشعر صناعي
struct Sensor {
    id: u32,
    name: String,
    unit: String,
    last_reading: f64,
    is_active: bool,
}

fn main() {
    // إنشاء مستشعر جديد
    let temp_sensor = Sensor {
        id: 101,
        name: String::from("مستشعر حرارة الفرن"),
        unit: String::from("°C"),
        last_reading: 85.3,
        is_active: true,
    };

    println!("المستشعر {}: {} = {} {}",
        temp_sensor.id, temp_sensor.name,
        temp_sensor.last_reading, temp_sensor.unit);
}

كتل impl: إضافة سلوك

كتل impl تربط الدوال بالهيكل، فيصبح للنوع سلوك خاص به.

struct Sensor {
    id: u32,
    name: String,
    unit: String,
    last_reading: f64,
    is_active: bool,
}

impl Sensor {
    // دالة منشئة (لا تأخذ self)
    fn new(id: u32, name: &str, unit: &str) -> Self {
        Sensor {
            id,
            name: String::from(name),
            unit: String::from(unit),
            last_reading: 0.0,
            is_active: true,
        }
    }

    // هل القراءة في النطاق الحرج؟
    fn is_critical(&self) -> bool {
        self.last_reading > 100.0 || self.last_reading < -20.0
    }

    // تحديث القراءة
    fn update_reading(&mut self, value: f64) {
        self.last_reading = value;
    }
}

fn main() {
    let mut sensor = Sensor::new(1, "ضغط الخط الرئيسي", "bar");
    sensor.update_reading(112.5);

    if sensor.is_critical() {
        println!("⚠ تحذير: {} في حالة حرجة!", sensor.name);
    }
}

هياكل الصف والهياكل الفارغة

هياكل الصف (Tuple Structs) تُعطي اسماً لمجموعة قيم بدون تسمية الحقول. الهياكل الفارغة (Unit Structs) تُمثّل حالة بدون بيانات.

// هياكل صف: تُغلّف قيمة واحدة بنوع ذي معنى
struct Temperature(f64);
struct Pressure(f64);
struct Voltage(f64);

// الهيكل الفارغ: يمثّل حالة بدون بيانات
struct Disconnected;

fn main() {
    let temp = Temperature(95.2);
    let pressure = Pressure(3.5);

    // النوع يمنعك من الخلط بين الحرارة والضغط عن طريق الخطأ
    // check_temperature(pressure); // خطأ في الترجمة!

    println!("الحرارة: {} درجة", temp.0);
    println!("الضغط: {} بار", pressure.0);
}

التعدادات: أنواع بمتغيرات

التعدادات (Enums) تصف قيمة يمكن أن تكون واحدة من عدة حالات محددة. هذا مثالي لنمذجة حالات الآلات في المصنع.

enum MachineState {
    Running,
    Idle,
    Error(String),
    Maintenance { until: String },
}

fn describe_state(state: &MachineState) {
    match state {
        MachineState::Running => println!("الآلة تعمل بشكل طبيعي"),
        MachineState::Idle => println!("الآلة في وضع الخمول"),
        MachineState::Error(msg) => println!("خطأ: {}", msg),
        MachineState::Maintenance { until } => {
            println!("صيانة حتى: {}", until);
        }
    }
}

التعدادات مع بيانات: قوة Rust الخارقة

كل متغير في التعداد يمكن أن يحمل بيانات مختلفة تماماً. هذه ميزة قوية لا تتوفر في معظم اللغات.

// كل نوع إنذار يحمل بيانات مختلفة
enum AlarmType {
    HighTemperature { current: f64, threshold: f64 },
    LowPressure(f64),
    CommunicationLost,
    CustomAlert(String, u8),  // رسالة + مستوى الخطورة
}

fn alarm_priority(alarm: &AlarmType) -> u8 {
    match alarm {
        AlarmType::HighTemperature { current, threshold }
            if *current > threshold * 1.5 => 1,  // أولوية قصوى
        AlarmType::HighTemperature { .. } => 2,
        AlarmType::LowPressure(_) => 2,
        AlarmType::CommunicationLost => 3,
        AlarmType::CustomAlert(_, level) => *level,
    }
}

match مع التعدادات: معالجة شاملة

المُترجم يُجبرك على معالجة كل حالة ممكنة. لا يمكنك نسيان حالة واحدة.

enum ProductionLine {
    Active { speed: f64 },
    Paused,
    Stopped(String),  // سبب التوقف
}

fn handle_line(line: &ProductionLine) -> String {
    // إذا أضفت متغيراً جديداً ونسيت معالجته هنا
    // المترجم سيرفض الترجمة!
    match line {
        ProductionLine::Active { speed } if *speed > 90.0 => {
            String::from("الخط يعمل بسرعة عالية")
        }
        ProductionLine::Active { speed } => {
            format!("الخط يعمل بسرعة {}%", speed)
        }
        ProductionLine::Paused => String::from("الخط متوقف مؤقتاً"),
        ProductionLine::Stopped(reason) => {
            format!("الخط متوقف: {}", reason)
        }
    }
}

مثال عملي: نظام إنذارات المصنع

نجمع الهياكل والتعدادات معاً لبناء نظام إنذارات كامل.

struct Alarm {
    sensor_id: u32,
    alarm_type: AlarmType,
    timestamp: String,
    acknowledged: bool,
}

enum AlarmType {
    OverTemperature(f64),
    UnderPressure(f64),
    VibrationExceeded { axis: String, value: f64 },
    DeviceOffline,
}

impl Alarm {
    fn severity(&self) -> &str {
        match &self.alarm_type {
            AlarmType::OverTemperature(t) if *t > 150.0 => "حرج",
            AlarmType::OverTemperature(_) => "تحذير",
            AlarmType::VibrationExceeded { value, .. } if *value > 10.0 => "حرج",
            AlarmType::DeviceOffline => "تحذير",
            _ => "معلومة",
        }
    }

    fn describe(&self) -> String {
        match &self.alarm_type {
            AlarmType::OverTemperature(t) =>
                format!("حرارة مرتفعة: {}°C", t),
            AlarmType::UnderPressure(p) =>
                format!("ضغط منخفض: {} bar", p),
            AlarmType::VibrationExceeded { axis, value } =>
                format!("اهتزاز محور {}: {} mm/s", axis, value),
            AlarmType::DeviceOffline =>
                String::from("الجهاز غير متصل"),
        }
    }
}

fn main() {
    let alarms = vec![
        Alarm {
            sensor_id: 101,
            alarm_type: AlarmType::OverTemperature(165.0),
            timestamp: String::from("2026-04-14 08:30"),
            acknowledged: false,
        },
        Alarm {
            sensor_id: 205,
            alarm_type: AlarmType::DeviceOffline,
            timestamp: String::from("2026-04-14 08:45"),
            acknowledged: false,
        },
    ];

    for alarm in &alarms {
        println!("[{}] مستشعر {} - {} ({})",
            alarm.timestamp, alarm.sensor_id,
            alarm.describe(), alarm.severity());
    }
}

الخلاصة

  • الهياكل تجمع بيانات مرتبطة في نوع واحد ذي اسم واضح
  • كتل impl تضيف دوالاً وسلوكاً مرتبطاً بالهيكل
  • هياكل الصف تُغلّف قيمة بنوع جديد يمنع الخلط
  • التعدادات تصف قيمة لها عدة حالات ممكنة
  • كل متغير في التعداد يمكنه حمل بيانات مختلفة
  • match يُجبرك على معالجة كل حالة — لا تنسى شيئاً
  • الجمع بين الهياكل والتعدادات يُنتج نماذج بيانات قوية وآمنة
struct enum impl methods tuple-struct associated-functions الهياكل التعدادات الأساليب نمذجة البيانات أنواع مخصصة بنية البيانات