From و Into
جزء من قسم Object Oriented Programming في رحلة Rust على Coddy — الدرس 57 من 61.
يعد التحويل بين الأنواع مهمة شائعة في لغة Rust. توفر سمة From طريقة موحدة لتحديد كيفية إنشاء نوع من نوع آخر. عندما تقوم بتنفيذ From، ستحصل على سمة Into تلقائياً وبشكل مجاني.
لتنفيذ From، تقوم بتعريف كيفية بناء نوعك من نوع آخر:
struct Meters(f64);
struct Kilometers(f64);
impl From<Kilometers> for Meters {
fn from(km: Kilometers) -> Self {
Meters(km.0 * 1000.0)
}
}
الآن يمكنك التحويل باستخدام إما دالة from أو أسلوب into:
let distance = Kilometers(5.0);
// باستخدام From بشكل صريح
let m1 = Meters::from(distance);
// باستخدام Into (يعمل لأن From تم تنفيذها)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();
تتطلب الطريقة into() تعليقاً توضيحياً للنوع (type annotation) لأن لغة Rust تحتاج إلى معرفة النوع الذي تقوم بالتحويل إليه. هذا النمط مفيد بشكل خاص عندما يكون لديك هياكل مساعدة (helper structs) تحتاج إلى تحويلها إلى أنواعك الأساسية - مثل تحويل بيانات التكوين (configuration data) إلى كائن مهيأ، أو تحويل المدخلات الخام إلى هيكل تم التحقق من صحته.
التحدي
سهللنقم ببناء نظام لتحويل درجات الحرارة باستخدام سمة From! ستقوم بإنشاء نوعين لدرجة الحرارة—Celsius و Fahrenheit—وتنفيذ التحويلات بينهما باستخدام سمات التحويل القياسية في Rust.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
temperature.rs: قم بتعريف هيكلين عامين من نوع newtype—وهماCelsiusوFahrenheit—كلاهما يغلف نوعf64. قم بتنفيذ سمةFromلتحويلCelsiusإلىFahrenheitباستخدام الصيغة:fahrenheit = celsius × 1.8 + 32.0. أضف أيضاً طريقةvalueلكل هيكل تعيد قيمةf64الداخلية.main.rs: قم باستيراد وحدة درجة الحرارة الخاصة بك واستعرض كلا طريقتي التحويل. أنشئ قيمةCelsiusمن المدخلات المقدمة، ثم حولها إلىFahrenheitباستخدامFahrenheit::from(). أنشئ قيمةCelsiusأخرى وقم بتحويلها باستخدام طريقة.into(). اطبع كلتا النتيجتين.
صيغة التحويل من Celsius إلى Fahrenheit هي: اضرب في 1.8 وأضف 32. تذكر أن تنفيذ From<Celsius> for Fahrenheit يمنحك تلقائياً سمة Into<Fahrenheit> على Celsius مجاناً!
يجب أن يعرض مخرجك كلا التحويلين بهذا التنسيق:
From: {celsius1}C = {fahrenheit1}F
Into: {celsius2}C = {fahrenheit2}Fعلى سبيل المثال، مع المدخلات 0 و 100:
From: 0C = 32F
Into: 100C = 212Fومع المدخلات 25 و -40:
From: 25C = 77F
Into: -40C = -40Fستتلقى مدخلين: قيمة Celsius الأولى (قم بتحليلها كـ f64) وقيمة Celsius الثانية (قم بتحليلها كـ f64).
ورقة مرجعية
توفر سمة From طريقة موحدة للتحويل بين الأنواع. عندما تقوم بتنفيذ From، فإنك تحصل تلقائياً على سمة Into مجاناً.
لتنفيذ From، حدد كيفية إنشاء نوعك من نوع آخر:
struct Meters(f64);
struct Kilometers(f64);
impl From<Kilometers> for Meters {
fn from(km: Kilometers) -> Self {
Meters(km.0 * 1000.0)
}
}
يمكنك التحويل باستخدام إما دالة from أو طريقة into:
let distance = Kilometers(5.0);
// Using From explicitly
let m1 = Meters::from(distance);
// Using Into (requires type annotation)
let distance = Kilometers(3.0);
let m2: Meters = distance.into();
تتطلب طريقة into() توضيحاً للنوع (type annotation) حتى تعرف لغة Rust النوع الذي تقوم بالتحويل إليه.
جرّب بنفسك
mod temperature;
use temperature::{Celsius, Fahrenheit};
fn main() {
// قراءة المدخلات
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let celsius1: f64 = input1.trim().parse().expect("Invalid number");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let celsius2: f64 = input2.trim().parse().expect("Invalid number");
// TODO: celsius1 من Celsius قم بإنشاء قيمة
// TODO: Fahrenheit::from() باستخدام Fahrenheit قم بتحويلها إلى
// TODO: celsius2 من Celsius قم بإنشاء قيمة أخرى
// TODO: .into() باستخدام Fahrenheit قم بتحويلها إلى
// TODO: :اطبع النتائج بالتنسيق التالي
// From: {celsius1}C = {fahrenheit1}F
// Into: {celsius2}C = {fahrenheit2}F
}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس 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 مع المعاملاتملخص - مشغل الوسائط