فهم المفاهيم وراء تنظيم التعليمات البرمجية
قبل أن نبدأ، من المهم شرح المفاهيم وراء تنظيم التعليمات البرمجية في برامج Rust:
- حزمة:
- تحتوي على وظائف داخل صندوقواحد أو أكثر.
- تتضمن معلومات حول كيفية إنشاء تلك الصناديق. المعلومات موجودة في ملف
Cargo.toml
.
- صندوق:
- هو وحدة تحويل برمجي، وهي أصغر مقدار من التعليمات البرمجية التي يمكن أن يعمل عليها برنامج التحويل البرمجي Rust.
- بمجرد اكتمال التحويل البرمجي، يُنتج إما برنامجًا قابلاً للتنفيذ أو مكتبة تعليمات برمجية.
- يحتوي على وحدة نمطية ضمنية غير مسماة ذات مستوى أعلى.
- وحدة نمطية:
- هي وحدة (ربما متداخلة) من تنظيم التعليمات البرمجية داخل صندوق.
- يمكن أن يكون لها تعريفات متكررة ضمن وحدات نمطية إضافية.
الحزمة
كلما قمنا بتشغيل الأمر $ cargo new <project-name>
، ينشئ Cargo حزمة لنا:
$ cargo new my-project
Created binary (application) `my-project` package
هنا، لدينا حزمة تحتوي فقط على src/main.rs
، ما يعني أنها تحتوي فقط على صندوق ثنائي يسمى my-project
:
my-project
├── src
│ └── main.rs
└── Cargo.toml
يمكن أن تحتوي الحزمة على صناديق ثنائية متعددة عن طريق وضع الملفات في src/bin
الدليل. سيكون كل ملف صندوقًا ثنائيًا منفصلاً.
إذا كانت الحزمة تحتوي على و src/lib.rs
، تحتوي على src/main.rs
صندوقين: مكتبة وثنائية. وكلاهما له نفس اسم الحزمة.
الصناديق
يركز نموذج التحويل البرمجي ل Rust على البيانات الاصطناعية التي تسمى الصناديق التي يمكن تحويلها برمجيا إلى ثنائي أو إلى مكتبة.
كل مشروع تقوم بإنشائه باستخدام cargo new
الأمر هو صندوق نفسه. كافة تعليمات Rust البرمجية لجهة أخرى والتي يمكنك استخدامها كتبعيات في المشروع هي أيضًا، كل واحدة منها، صندوق واحد.
صناديق المكتبة
لقد قمنا بالفعل بتناول كيفية إنشاء برنامج ثنائي، وإنشاء مكتبة يكون بنفس السهولة. لإنشاء مكتبة، مرر معلمة --lib
سطر الأوامر إلى cargo new
الأمر :
$ cargo new --lib my-library
Created library `my-library` package
يمكنك أن ترى أنه بدلا من src/main.rs
ملف، يمكنك الآن الحصول على ملف =src/lib.rs.
my-library
├── src
│ └── lib.rs
└── Cargo.toml
عندما تخبر Cargo بتجميع هذا الصندوق، ستحصل على ملف مكتبة يسمى libmy_library.rlib
يمكن نشره وربطه بمشاريع أخرى.
الوحدات
يوفر Rust نظامًا قويًا للوحدة النمطية يمكن استخدامه لتقسيم التعليمات البرمجية بشكل هرمي إلى وحدات نمطية منطقية تسهّل أيضًا القراءة وإعادة الاستخدام.
الوحدة النمطية هي مجموعة من العناصر:
- الثوابت
- الأسماء المستعارة للنوع
- الدالات
- البنيات
- التعدادات
- السمات
impl
كتل- وحدات نمطية أخرى
تتحكم الوحدات أيضًا في خصوصية العنصر. تعرّف خصوصية العنصر أن العنصر إما عام وإما خاص. يعني العنصر العام أنه يمكن استخدامه من قِبَل التعليمات البرمجية الخارجية. يعني العنصر الخاص أن العنصر عبارة عن تفاصيل تنفيذ داخلية وأنه غير متاح للاستخدام الخارجي.
مثال حول وحدة نمطية:
mod math {
type Complex = (f64, f64);
pub fn sin(f: f64) -> f64 { /* ... */ }
pub fn cos(f: f64) -> f64 { /* ... */ }
pub fn tan(f: f64) -> f64 { /* ... */ }
}
println!("{}", math::cos(45.0));
إذا كان الملف المصدر يحتوي mod
على إعلانات، فسيتم إدراج محتويات ملفات الوحدة النمطية في الأماكن التي mod
يتم فيها العثور على التعريفات في الملف المصدر، قبل تشغيل المحول البرمجي فوقه. وبعبارة أخرى، لا يتمّ تحويل الوحدات النمطية برمجيًا بشكل فردي، فقط الصناديق يتم تحويلها برمجيًا.
ربما لاحظت pub
الكلمة الأساسية في بداية تعريفات الدالة في الوحدة النمطية math
.
يتحقق برنامج التحويل البرمجي Rust لمعرفة ما إذا كان يمكن استخدام العناصر عبر الوحدات أم لا. افتراضيًا، كل شيء في Rust خاص ويمكن الوصول إليه فقط من قبل الوحدة الحالية وتوابعها. في المقابل، عندما يتم الإعلان عن عنصر على pub
أنه ، يمكن اعتباره متاحا للعالم الخارجي. على سبيل المثال:
// Declare a private struct
struct Foo;
// Declare a public struct with a private field
pub struct Bar {
field: i32,
}
// Declare a public enum with two public variants
pub enum State {
PubliclyAccessibleVariant,
PubliclyAccessibleVariant2,
}
قواعد الخصوصية في Rust قوية بشكل مدهش لإنشاء التسلسلات الهرمية للوحدات النمطية التي تعرض واجهات برمجة التطبيقات العامة مع إخفاء تفاصيل التنفيذ الداخلي.