سمة Display
جزء من قسم Object Oriented Programming في رحلة Rust على Coddy — الدرس 36 من 61.
بينما تُعد Debug رائعة للمطورين الذين يفحصون البيانات، فإن سمة Display مُصممة لـ المخرجات الموجهة للمستخدم. وهي ما يشغل المنسق {} في println!. وعلى عكس Debug، لا يمكن لـ Rust اشتقاق Display تلقائيًا—يجب عليك تنفيذها يدويًا.
لتنفيذ Display، تحتاج إلى استيراد وحدة fmt وتنفيذ دالة fmt:
use std::fmt;
struct Temperature {
celsius: f64,
}
impl fmt::Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}°C", self.celsius)
}
}
تستقبل طريقة fmt كائن Formatter وتُرجع fmt::Result. تستخدم ماكرو write! لتنسيق مخرجاتك، مع الوصول إلى حقول الهيكل (struct) من خلال self.
يمكنك الآن طباعة الـ struct باستخدام المنسق القياسي {}:
let temp = Temperature { celsius: 23.5 };
println!("{}", temp); // 23.5°C
الفرق الرئيسي: يُظهر مخرج Debug هيكلية بياناتك (مفيد لتصحيح الأخطاء)، بينما مخرج Display يكون منسقاً ومخصصاً للمستخدمين النهائيين. يمكن للـ struct تنفيذ كليهما—استخدم {:?} لتصحيح الأخطاء و {} للحصول على مخرجات نظيفة.
التحدي
سهللنقم بإنشاء نظام عرض منتجات سهل الاستخدام! بينما تُظهر سمة Debug البنية الخام لبياناتك، تتيح لك سمة Display صياغة مخرجات مصقولة وقابلة للقراءة من قبل البشر، وهي مثالية للمستخدمين النهائيين.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
product.rs: قم بتعريف هيكلProductعام مع حقلين عامين:name(String) وprice(f64). قم بتنفيذ سمةDisplayلهيكلك بحيث يتم تنسيقه كـ{name} - ${price}. تذكر استيرادstd::fmtواستخدام ماكروwrite!داخل تابعfmtالخاص بك.main.rs: قم باستيراد وحدة المنتج الخاصة بك وأنشئ مثيلاً منProductباستخدام المدخلات المقدمة. اطبع المنتج باستخدام منسق{}القياسي لعرض مخرجات العرض المخصصة الخاصة بك.
تتطلب سمة Display منك تنفيذ تابع fmt يدويًا—لا يمكن لـ Rust اشتقاقه تلقائيًا مثل Debug. يمنحك هذا تحكمًا كاملاً في كيفية ظهور نوع بياناتك للمستخدمين.
يجب أن يعرض مخرجك المنتج بتنسيق نظيف وسهل الاستخدام:
{name} - ${price}على سبيل المثال، مع المدخلات Wireless Mouse و 29.99:
Wireless Mouse - $29.99ستتلقى مدخلين: اسم المنتج والسعر (قم بتحليله كـ f64).
ورقة مرجعية
تم تصميم سمة (trait) الـ Display من أجل المخرجات الموجهة للمستخدم وهي التي تشغل منسق {} في println!. وعلى عكس Debug، يجب تنفيذها يدوياً.
لتنفيذ Display، قم باستيراد وحدة fmt ونفذ دالة fmt:
use std::fmt;
struct Temperature {
celsius: f64,
}
impl fmt::Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}°C", self.celsius)
}
}
تستقبل دالة fmt كائن Formatter وتُرجع fmt::Result. استخدم ماكرو write! لتنسيق المخرجات، مع الوصول إلى حقول الهيكل (struct) عبر self.
اطبع الهيكل باستخدام منسق {}:
let temp = Temperature { celsius: 23.5 };
println!("{}", temp); // 23.5°C
الفرق الرئيسي: تعرض Debug ({:?}) هيكل البيانات لأغراض تصحيح الأخطاء، بينما توفر Display ({}) مخرجات منسقة للمستخدمين النهائيين.
جرّب بنفسك
mod product;
use product::Product;
fn main() {
let mut name = String::new();
std::io::stdin().read_line(&mut name).expect("Failed to read line");
let name = name.trim().to_string();
let mut price_input = String::new();
std::io::stdin().read_line(&mut price_input).expect("Failed to read line");
let price: f64 = price_input.trim().parse().expect("Failed to parse price");
// TODO: إنشاء مثيل (instance) من Product باستخدام الاسم والسعر
// TODO: طباعة المنتج باستخدام المنسق {}
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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 مع المعاملاتملخص - مشغل الوسائط