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

التركيب

جزء من قسم Object Oriented Programming في رحلة Rust على Coddy — الدرس 55 من 61.

تعتمد العديد من اللغات كائنية التوجه بشكل كبير على الوراثة لمشاركة الوظائف بين الأنواع. تتخذ لغة رُست (Rust) نهجاً مختلفاً: التركيب (composition). فبدلاً من وراثة السلوك من فئة أب، يمكنك بناء أنواع معقدة من خلال تضمين أنواع أخرى كحقول.

فكر في نمذجة سيارة. بدلاً من إنشاء فئة Vehicle أساسية والوراثة منها، فإنك تقوم بتكوين Car من مكونات أصغر وأكثر تركيزاً:

struct Engine {
    horsepower: u32,
}

struct Wheels {
    count: u8,
    diameter: f32,
}

struct Car {
    engine: Engine,
    wheels: Wheels,
    brand: String,
}

لا يرث Car من Engine أو Wheels—بل هو يمتلكها. علاقة "has-a" هذه هي التركيب (composition). يمكنك الوصول إلى المكونات الداخلية من خلال حقولها (fields) واستدعاء دوالها (methods) مباشرة:

impl Engine {
    fn start(&self) {
        println!("Engine with {} HP started!", self.horsepower);
    }
}

impl Car {
    fn start(&self) {
        self.engine.start();  // تفويض إلى المكون الداخلي
    }
}

يحافظ هذا النمط على تركيز كل struct على مسؤولية واحدة. هل تحتاج إلى تغيير كيفية عمل المحركات؟ قم بتعديل الـ Engine struct فقط. هل تريد إعادة استخدام Wheels لدراجة نارية؟ ما عليك سوى تضمينها في struct جديد. يمنحك التركيب (Composition) المرونة دون الارتباط الوثيق (tight coupling) الذي غالباً ما يخلقه التوريث (inheritance).

challenge icon

التحدي

سهل

لنقم ببناء نظام حاسوب باستخدام التركيب (composition)! بدلاً من إنشاء هيكل واحد ضخم، ستقوم بتركيب Computer من مكونات أصغر وأكثر تركيزاً—وهي CPU و Memory. سيعرف كل مكون كيفية وصف نفسه، وسيقوم الـ Computer بتفويض المهام إلى أجزائه.

ستقوم بتنظيم الكود الخاص بك عبر ثلاثة ملفات:

  • cpu.rs: قم بتعريف هيكل CPU عام (public) مع حقلين عامين: cores (u32) لعدد الأنوية، و speed_ghz (f32) لسرعة الساعة. أضف ميثود specs تعيد سلسلة نصية (String) تصف المعالج بالتنسيق "{cores}-core @ {speed_ghz}GHz".
  • memory.rs: قم بتعريف هيكل Memory عام مع حقل عام size_gb (u32) لحجم الذاكرة. أضف ميثود specs تعيد سلسلة نصية بالتنسيق "{size_gb}GB RAM".
  • main.rs: قم باستيراد كلا الموديولين وأنشئ هيكل Computer عام يحتوي على حقل cpu من نوع CPU وحقل memory من نوع Memory. قم بتنفيذ ميثود system_info على الـ Computer تقوم بالتفويض لمكوناته وتطبع مواصفات النظام الكاملة. استخدم المدخلات المقدمة لبناء Computer وعرض معلوماته.

يجب أن تقوم ميثود system_info بطباعة:

System: {cpu_specs} | {memory_specs}

على سبيل المثال، مع المدخلات 8 و 3.5 و 16:

System: 8-core @ 3.5GHz | 16GB RAM

ومع المدخلات 4 و 2.8 و 32:

System: 4-core @ 2.8GHz | 32GB RAM

ستتلقى ثلاثة مدخلات: أنوية المعالج (قم بتحويلها إلى u32)، سرعة المعالج (قم بتحويلها إلى f32)، وحجم الذاكرة (قم بتحويلها إلى u32).

ورقة مرجعية

تستخدم لغة Rust التركيب (composition) بدلاً من الوراثة لمشاركة الوظائف بين الأنواع. يمكنك بناء أنواع معقدة من خلال تضمين أنواع أخرى كحقول، مما يؤدي إلى إنشاء علاقة "يحتوي على" (has-a).

التركيب الأساسي

قم بتعريف هياكل (structs) أصغر وأكثر تركيزاً وقم بتركيبها في هياكل أكبر:

struct Engine {
    horsepower: u32,
}

struct Wheels {
    count: u8,
    diameter: f32,
}

struct Car {
    engine: Engine,
    wheels: Wheels,
    brand: String,
}

التفويض للمكونات

يمكنك الوصول إلى المكونات الداخلية من خلال حقولها واستدعاء دوالها (methods):

impl Engine {
    fn start(&self) {
        println!("Engine with {} HP started!", self.horsepower);
    }
}

impl Car {
    fn start(&self) {
        self.engine.start();  // التفويض للمكون الداخلي
    }
}

يحافظ التركيب على تركيز كل هيكل (struct) على مسؤولية واحدة، مما يوفر المرونة دون اقتران وثيق.

جرّب بنفسك

mod cpu;
mod memory;

use cpu::CPU;
use memory::Memory;

// TODO: قم بتعريف هيكل Computer عام مع حقلين عامين:
// - cpu: CPU
// - memory: Memory

// TODO: قم بتنفيذ طريقة system_info على Computer بحيث:
// - تقوم بالتفويض إلى cpu.specs() و memory.specs()
// - تطبع: System: {cpu_specs} | {memory_specs}

fn main() {
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let cores: u32 = input.trim().parse().expect("Invalid number");
    
    input.clear();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let speed_ghz: f32 = input.trim().parse().expect("Invalid number");
    
    input.clear();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let size_gb: u32 = input.trim().parse().expect("Invalid number");
    
    // TODO: قم بإنشاء مثيلات CPU و Memory باستخدام المدخلات التي تم تحليلها
    
    // TODO: قم بإنشاء مثيل Computer مع CPU و Memory
    
    // TODO: قم باستدعاء system_info() على الكمبيوتر لطباعة النتيجة
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming