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

تنفيذ الـ Traits

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

الآن بعد أن عرفت كيفية تعريف trait، دعنا نرى كيفية جعل struct يفي بهذا العقد. إن تنفيذ trait يربط المتطلبات المجردة بالسلوك الملموس.

تستخدم الصيغة impl TraitName for StructName:

trait Speak {
    fn speak(&self) -> String;
}

struct Dog {
    name: String,
}

impl Speak for Dog {
    fn speak(&self) -> String {
        format!("{} says: Woof!", self.name)
    }
}

تخبر كتلة impl Speak for Dog لغة Rust أن Dog تقوم بتنفيذ سمة Speak. في الداخل، ستقوم بتوفير جسم الطريقة الفعلي—هذا هو المكان الذي تحدد فيه كيف يتحدث الكلب.

تتضح قوة السمات (traits) عندما تقوم أنواع متعددة بتطبيق السمة نفسها:

struct Cat {
    name: String,
}

impl Speak for Cat {
    fn speak(&self) -> String {
        format!("{} says: Meow!", self.name)
    }
}

كلا من Dog و Cat يتشاركان الآن في قدرة Speak، ولكن كل منهما يقدم تنفيذه الفريد الخاص. يمكنك استدعاء .speak() على أي من النوعين:

let dog = Dog { name: String::from("Rex") };
let cat = Cat { name: String::from("Whiskers") };

println!("{}", dog.speak());  // Rex يقول: Woof!
println!("{}", cat.speak());  // Whiskers يقول: Meow!

هذا هو أساس تعدد الأشكال (polymorphism) في Rust - أنواع مختلفة، نفس الواجهة، وسلوكيات فريدة.

challenge icon

التحدي

سهل

دعنا نبث الحياة في السمات (traits) من خلال تنفيذها لأنواع مختلفة! ستقوم بإنشاء سمة Describable وتنفيذها لهيكلين (structs) مختلفين، حيث يقدم كل منهما وصفه الفريد الخاص.

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

  • describable.rs: قم بتعريف سمة Describable عامة مع دالة describe(&self) -> String.
  • items.rs: قم بإنشاء هيكلين عامين ينفذان السمات الخاصة بك:
    • Book مع حقل title عام (String)
    • Movie مع حقل name عام (String)
    يجب أن ينفذ كل هيكل سمة Describable بتنسيق وصف فريد خاص به.
  • main.rs: اجمع وحداتك معاً، وأنشئ مثيلات (instances) من كلا الهيكلين، واستدعِ دوال describe الخاصة بهما لإظهار كيف تنتج نفس السمة مخرجات مختلفة لأنواع مختلفة.

يجب أن يصف Book نفسه كـ Book: {title} ويجب أن يصف Movie نفسه كـ Film: {name}. لاحظ كيف يلبي كل نوع نفس العقد ولكن بسلوكه الخاص!

في ملفك الرئيسي، قم بإنشاء كتاب وفيلم باستخدام المدخلين المقدمين، ثم اطبع أوصافهما في أسطر منفصلة.

يجب أن يتبع مخرجك هذا التنسيق:

Book: {title}
Film: {name}

على سبيل المثال، مع المدخلات 1984 و Inception:

Book: 1984
Film: Inception

ستتلقى مدخلين: عنوان كتاب واسم فيلم.

ورقة مرجعية

لتنفيذ سمة (trait) لهيكل (struct)، استخدم صيغة impl TraitName for StructName:

trait Speak {
    fn speak(&self) -> String;
}

struct Dog {
    name: String,
}

impl Speak for Dog {
    fn speak(&self) -> String {
        format!("{} says: Woof!", self.name)
    }
}

يمكن لأنواع متعددة تنفيذ نفس السمة بسلوكيات مختلفة:

struct Cat {
    name: String,
}

impl Speak for Cat {
    fn speak(&self) -> String {
        format!("{} says: Meow!", self.name)
    }
}

let dog = Dog { name: String::from("Rex") };
let cat = Cat { name: String::from("Whiskers") };

println!("{}", dog.speak());  // Rex says: Woof!
println!("{}", cat.speak());  // Whiskers says: Meow!

يتيح ذلك تعدد الأشكال (polymorphism) في لغة Rust — حيث تشترك أنواع مختلفة في نفس الواجهة مع تنفيذات فريدة.

جرّب بنفسك

mod describable;
mod items;

use describable::Describable;
use items::{Book, Movie};

fn main() {
    // قراءة المدخلات
    let mut title = String::new();
    std::io::stdin().read_line(&mut title).expect("Failed to read line");
    let title = title.trim().to_string();
    
    let mut name = String::new();
    std::io::stdin().read_line(&mut name).expect("Failed to read line");
    let name = name.trim().to_string();
    
    // TODO: إنشاء مثيل (instance) من Book بالعنوان
    
    // TODO: إنشاء مثيل (instance) من Movie بالاسم
    
    // TODO: طباعة وصف الكتاب
    
    // TODO: طباعة وصف الفيلم
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming