أنواع عامة متعددة
جزء من قسم Object Oriented Programming في رحلة Rust على Coddy — الدرس 26 من 61.
أحياناً لا يكون المعامل العام الواحد كافياً. ماذا لو كنت بحاجة إلى struct يحمل قيمتين، وقد تكون هاتان القيمتان من نوعين مختلفين؟ تسمح لك لغة Rust باستخدام معاملات عامة متعددة عن طريق الفصل بينها بفاصلات.
إليك هيكل Pair الذي يحتوي على قيمتين من أنواع قد تكون مختلفة:
struct Pair<T, U> {
first: T,
second: U,
}
يقوم الـ <T, U> بالتصريح عن معاملي نوع مستقلين. يمكن أن يكون T و U من نفس النوع، أو مختلفين تماماً - الأمر متروك لك عند إنشاء مثيل:
let both_ints = Pair { first: 10, second: 20 }; // T=i32, U=i32
let mixed = Pair { first: "hello", second: 3.14 }; // T=&str, U=f64
let reversed = Pair { first: 100, second: "world" }; // T=i32, U=&str
عند تنفيذ الأساليب (methods)، تقوم بالتصريح عن جميع المعلمات العامة (generic parameters) في كتلة impl:
impl<T, U> Pair<T, U> {
fn get_first(&self) -> &T {
&self.first
}
fn get_second(&self) -> &U {
&self.second
}
}
هذا النمط شائع عندما تحتاج إلى ربط قطعتين من البيانات المرتبطة ولكن من المحتمل أن تكونا مختلفتين—مثل زوج (مفتاح-قيمة)، أو إحداثيات بأنواع رقمية مختلفة، أو نتيجة مقترنة ببيانات وصفية.
التحدي
سهللنقم ببناء نظام تخزين مفتاح-قيمة (key-value) يوضح قوة الأنواع العامة المتعددة (multiple generic types)! ستقوم بإنشاء هيكل KeyValue يمكنه الربط بين أي نوعين معاً—وهو أمر مثالي لربط العناوين بالبيانات، أو المعرفات (IDs) بالكائنات، أو أي مزيج آخر.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
keyvalue.rs: قم بتعريف هيكل عام عام (public generic struct) يسمىKeyValue<K, V>مع حقلين خاصين (private fields):keyمن النوعKوvalueمن النوعV. قم بتنفيذ دوال (methods) للعمل مع هذا الهيكل:- دالة مرتبطة (associated function) تسمى
newتقوم بإنشاءKeyValueمن مفتاح وقيمة. - دالة
keyتعيد مرجعاً (reference) للمفتاح. - دالة
valueتعيد مرجعاً (reference) للقيمة. - دالة
set_valueتقوم باستبدال القيمة الحالية بقيمة جديدة.
- دالة مرتبطة (associated function) تسمى
main.rs: قم باستيراد الوحدة (module) الخاصة بك ووضح كيف يعمل نفس تعريف الهيكل مع تركيبات أنواع مختلفة. ستقوم بإنشاء أزواج مفتاح-قيمة بأنواع مختلطة لإظهار مرونة الأنواع العامة المتعددة.
في ملفك الرئيسي، قم بإنشاء والعمل مع أزواج المفتاح-القيمة التالية:
- زوج بمفتاح نصي (string) وقيمة عددية (integer) (المدخل الأول كمفتاح، والمدخل الثاني يتم تحويله إلى
i32كقيمة). - اطبع المفتاح والقيمة.
- قم بتحديث القيمة إلى عدد صحيح جديد (المدخل الثالث يتم تحويله إلى
i32). - اطبع القيمة المحدثة.
- أنشئ زوجاً ثانياً بمفتاح عددي وقيمة نصية (المدخل الرابع يتم تحويله إلى
i32كمفتاح، والمدخل الخامس كقيمة). - اطبع المفتاح والقيمة لهذا الزوج.
يجب أن يتبع مخرجك هذا التنسيق:
Key: {key}, Value: {value}
Updated value: {value}
Key: {key}, Value: {value}على سبيل المثال، مع المدخلات name، و 42، و 100، و 7، و lucky:
Key: name, Value: 42
Updated value: 100
Key: 7, Value: luckyلاحظ كيف يستخدم الزوج الأول KeyValue<String, i32> بينما يستخدم الثاني KeyValue<i32, String>—نفس الهيكل، ولكن بتركيبات أنواع مختلفة!
ستتلقى خمسة مدخلات: مفتاح نصي، قيمة عددية، عدد صحيح بديل، مفتاح عددي، وقيمة نصية.
جرّب بنفسك
mod keyvalue;
use keyvalue::KeyValue;
fn main() {
// قراءة خمسة مدخلات
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let string_key = input1.trim().to_string();
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let int_value: i32 = input2.trim().parse().expect("Failed to parse");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let replacement_int: i32 = input3.trim().parse().expect("Failed to parse");
let mut input4 = String::new();
std::io::stdin().read_line(&mut input4).expect("Failed to read line");
let int_key: i32 = input4.trim().parse().expect("Failed to parse");
let mut input5 = String::new();
std::io::stdin().read_line(&mut input5).expect("Failed to read line");
let string_value = input5.trim().to_string();
// TODO: إنشاء زوج KeyValue<String, i32> باستخدام string_key و int_value
// TODO: طباعة المفتاح والقيمة بالتنسيق: "Key: {key}, Value: {value}"
// TODO: تحديث القيمة باستخدام set_value مع replacement_int
// TODO: طباعة القيمة المحدثة بالتنسيق: "Updated value: {value}"
// TODO: إنشاء زوج KeyValue<i32, String> باستخدام int_key و string_value
// TODO: طباعة المفتاح والقيمة لهذا الزوج بالتنسيق: "Key: {key}, Value: {value}"
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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 مع المعاملاتملخص - مشغل الوسائط