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

إرجاع الأنواع باستخدام Traits

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

لقد استخدمت قيود السمات (trait bounds) لتقييد الأنواع التي يمكن للدالة قبولها. ولكن ماذا عن ما تعيده الدالة؟ تتيح لك صيغة impl Trait تحديد أن الدالة تعيد "نوعًا ما يطبق هذه السمة" دون تسمية النوع الملموس (concrete type).

إليك بناء الجملة البرمجية قيد التنفيذ:

trait Summary {
    fn summarize(&self) -> String;
}

struct Article {
    headline: String,
}

impl Summary for Article {
    fn summarize(&self) -> String {
        self.headline.clone()
    }
}

fn create_summary() -> impl Summary {
    Article { headline: String::from("Breaking News!") }
}

نوع الإرجاع impl Summary يخبر المستدعين "بأنك ستحصل على شيء ينفذ Summary." يمكن للمستدعي استخدام أي طريقة من السمة (trait)، ولكنه لا يحتاج إلى معرفة أن النوع الفعلي هو Article.

هذا مفيد بشكل خاص عندما يكون النوع الملموس (concrete type) معقداً أو عندما تريد إخفاء تفاصيل التنفيذ. تَعِد الدالة بقدرة معينة (السمة - trait)، وليس بنوع محدد.

ومع ذلك، هناك قيد مهم: يجب أن تعيد الدالة نوعاً ملموساً (concrete type) واحداً بالضبط. لا يمكنك إعادة أنواع مختلفة تنفذ نفس السمة (trait) بشكل مشروط - فهذا يتطلب كائنات السمات (trait objects)، والتي ستتعلم عنها لاحقاً.

// هذا يعمل - يعيد دائماً Article
fn make_item() -> impl Summary {
    Article { headline: String::from("Hello") }
}

// هذا لن يتم تجميعه - نوعان مختلفان
// fn make_item(flag: bool) -> impl Summary {
//     if flag { Article { ... } } else { Tweet { ... } }
// }
challenge icon

التحدي

سهل

لنقم ببناء مصنع لبطاقات المعايدة يستخدم نوع الإرجاع impl Trait لإخفاء تفاصيل التنفيذ! ستقوم بإنشاء دالة تُرجع "شيئاً يمكنه إلقاء التحية" دون الكشف عن النوع الملموس للمستدعي.

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

  • greetings.rs: قم بتعريف سمة (trait) عامة باسم Greet مع طريقة greet تأخذ &self وتُرجع String. ثم أنشئ هيكلاً (struct) باسم Card (لا يلزم أن يكون عاماً!) مع حقل message من نوع (String). قم بتنفيذ سمة Greet للهيكل Card، بحيث تُرجع الرسالة. أخيراً، أنشئ دالة عامة تسمى create_greeting تأخذ معامل String وتُرجع impl Greet. يجب أن تقوم هذه الدالة بإنشاء وإرجاع Card بالرسالة المعطاة.
  • main.rs: قم باستيراد وحدة greetings الخاصة بك واستخدم المدخلات المقدمة لاستدعاء create_greeting. الجمال هنا هو أن ملفك الرئيسي لا يعرف شيئاً عن النوع Card على الإطلاق — فهو يعرف فقط أنه تلقى شيئاً ينفذ Greet. استدعِ طريقة greet على القيمة المرجعة واطبع النتيجة.

البصيرة الأساسية هي أن Card يظل خاصاً بالوحدة، ولكن لا يزال بإمكان المستدعين استخدامه من خلال واجهة السمة. تَعِد الدالة بقدرة (التحية)، وليس بنوع محدد.

يجب أن يعرض مخرجك التحية:

{message}

على سبيل المثال، مع المدخل Happy Birthday!:

Happy Birthday!

ومع المدخل Congratulations on your promotion!:

Congratulations on your promotion!

ستتلقى مدخلاً واحداً: رسالة التحية.

جرّب بنفسك

mod greetings;

use greetings::Greet;

fn main() {
    // قراءة رسالة التحية من المدخلات
    let mut input = String::new();
    std::io::stdin().read_line(&mut input).expect("Failed to read line");
    let message = input.trim().to_string();

    // TODO: استدعاء create_greeting مع الرسالة
    // Note: لا تعرف النوع الملموس - فقط أنه يطبق Greet!
    
    // TODO: استدعاء الدالة greet وطباعة النتيجة
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming