استخدام الهياكل (Structs) لتنظيم البيانات في لغة رست (Rust)
تُعد لغة رست (Rust) واحدة من أكثر لغات البرمجة الحديثة التي حظيت باهتمام واسع في السنوات الأخيرة، نظرًا لما توفره من مزايا قوية تجمع بين الأداء العالي والأمان، بالإضافة إلى أدوات متقدمة لإدارة الذاكرة والتحكم في الأنظمة المعقدة. ومن بين الأدوات الأساسية التي تقدمها رست لتنظيم وإدارة البيانات هي الهياكل (Structs)، التي تُستخدم لتنظيم البيانات وتشكيل أنواع معقدة تحمل خصائص متعددة تحت كيان واحد.
في هذا المقال، سنقدم دراسة معمقة وشاملة حول مفهوم الهياكل في رست، كيفية استخدامها، مزاياها، وتطبيقاتها المختلفة، مع استعراض تفاصيل تقنية ودروس عملية تساعد المبرمجين على فهمها بشكل عميق ومتكامل.
تعريف الهياكل (Structs) في رست
الهياكل في رست تُعتبر نوعًا مركبًا (Compound Type) يسمح بتجميع مجموعة من القيم المرتبطة، والتي قد تكون من أنواع بيانات مختلفة، في كيان واحد. يمكن تشبيهها بالكائنات (Objects) في اللغات الأخرى، لكن رست تعتمد مفهوم الهيكل لتجميع البيانات فقط، بينما الخصائص المتعلقة بالسلوك (Methods) تُضاف عبر تعريف دوال مرتبطة.
الشكل العام لتعريف هيكل في رست يكون كالتالي:
ruststruct Person {
name: String,
age: u32,
email: String,
}
في هذا المثال، تم تعريف هيكل باسم Person يحتوي على ثلاثة حقول: الاسم (name) من نوع String، العمر (age) من نوع u32، والبريد الإلكتروني (email) من نوع String.
أهمية استخدام الهياكل
يعد استخدام الهياكل في رست أداة أساسية لتنظيم البيانات بحيث تصبح أكثر وضوحًا وقابلية للإدارة، مقارنة بالاعتماد على متغيرات منفصلة أو قوائم غير منظمة. الهياكل توفر عدة مزايا:
-
تجميع البيانات المتصلة: تسمح بتجميع المعلومات ذات العلاقة تحت كيان موحد، مما يسهل التعامل معها.
-
التحقق من الأنواع: بما أن كل حقل له نوع محدد، تضمن رست التحقق من صحة البيانات عند التجميع.
-
قابلية التوسع: يمكن تطوير الهياكل بسهولة بإضافة حقول جديدة دون الحاجة لتغيير الكود الذي يستخدم الهيكل بشكل كبير.
-
إمكانية إضافة دوال (Methods): يمكن ربط وظائف معينة بالهيكل، مما يحسن من تصميم البرنامج ويفصل بين البيانات والسلوك.
أنواع الهياكل في رست
يوجد في رست أنواع مختلفة من الهياكل، ولكل نوع خصائص واستخدامات مختلفة:
1. هياكل الحقول المسماة (Named Fields Structs)
وهي أكثر أنواع الهياكل شيوعًا، حيث يتم تعريف الحقول بأسماء واضحة كما في المثال السابق.
ruststruct Rectangle {
width: u32,
height: u32,
}
تُستخدم هذه الهياكل عندما نحتاج إلى تمثيل بيانات ذات خصائص متعددة.
2. هياكل الحقول غير المسماة (Tuple Structs)
تمثل هياكل مثل الـ Tuple، ولكن لها اسم خاص، ولا تحمل أسماء للحقول، فقط مواقعها:
ruststruct Color(u8, u8, u8);
تُستخدم عند عدم الحاجة لأسماء الحقول، وتكون مفيدة لتمثيل بيانات بسيطة متعددة الأجزاء.
3. هياكل الوحدة (Unit Structs)
هي هياكل لا تحتوي على أي حقول، وتُستخدم عادة لتحديد نوع معين يمكن استخدامه كعلامة أو لتعريف سلوك معين.
ruststruct Marker;
إنشاء كائنات من الهياكل
بعد تعريف الهيكل، يمكن إنشاء قيم منه بطرق مختلفة. على سبيل المثال:
rustlet user1 = Person {
name: String::from("Ahmad"),
age: 30,
email: String::from("[email protected]"),
};
يمكن أيضًا إنشاء نسخة جديدة مع تعديل بعض الحقول باستخدام تعبير “تحديث الهيكل” (struct update syntax):
rustlet user2 = Person {
name: String::from("Layla"),
..user1
};
في هذا المثال، user2 يرث القيم من user1 في الحقول غير المحددة.
الوصول إلى حقول الهيكل وتعديلها
يمكن الوصول إلى حقول الهيكل باستخدام نقطة (dot notation):
rustprintln!("User name is {}", user1.name);
لتعديل حقل معين، يجب أن يكون الهيكل متغيرًا (mutable):
rustlet mut user3 = user1;
user3.age = 31;
دوال مرتبطة بالهياكل (Methods and Associated Functions)
تدعم رست إضافة دوال خاصة بالهيكل باستخدام كتلة impl، ما يسمح بربط سلوكيات مع البيانات، مما يعزز مفهوم البرمجة الموجهة للكائنات.
مثال على ذلك:
rustimpl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}
هنا، area تحسب مساحة المستطيل، وcan_hold تتحقق مما إذا كان المستطيل الحالي يمكن أن يحتوي على مستطيل آخر.
ملكية البيانات والاقتراض في الهياكل
بما أن رست تعتمد نظام ملكية صارم لإدارة الذاكرة، عند استخدام الهياكل يجب مراعاة قواعد الملكية والاقتراض:
-
عند نقل ملكية هيكل أو حقله، لا يمكن استخدام القيمة القديمة إلا إذا كانت clonable.
-
عند اقتراض الهيكل (أو جزء منه)، يمكن استخدامه مؤقتًا مع الحفاظ على سلامة البيانات.
هذا النظام يساعد على منع مشاكل الذاكرة مثل الاستخدام بعد التحرير (Use After Free) والتسربات.
استخدام الهياكل مع الأنماط والأنواع المعرفة (Enums and Traits)
رست تدمج بين الهياكل وأنواع البيانات الأخرى مثل الـ Enum والـ Traits لتصميم برامج مرنة وقوية.
على سبيل المثال، يمكن تعريف هيكل يحتوي على حقل من نوع Enum:
rustenum Status {
Active,
Inactive,
Blocked,
}
struct User {
name: String,
status: Status,
}
كما يمكن للهياكل أن تنفذ Traits، التي تمثل سلوكيات عامة مشتركة:
rusttrait Describe {
fn describe(&self) -> String;
}
impl Describe for Person {
fn describe(&self) -> String {
format!("{} is {} years old", self.name, self.age)
}
}
الهياكل المتداخلة (Nested Structs)
من الممكن داخل هيكل أن يحتوي أحد الحقول على هيكل آخر، ما يسمح بإنشاء تراكيب بيانات معقدة ومنظمة بشكل هرمي:
ruststruct Address {
city: String,
country: String,
}
struct Person {
name: String,
address: Address,
}
يتيح ذلك تجميع المعلومات بطريقة منظمة تُمكّن من إعادة استخدام الهياكل داخل بعضها.
مثال عملي متكامل
لنفترض أننا نريد بناء نظام لإدارة مكتبة، حيث تحتوي المكتبة على كتب، ولكل كتاب مؤلف وتاريخ نشر:
ruststruct Author {
name: String,
birth_year: u32,
}
struct Book {
title: String,
author: Author,
published_year: u32,
}
impl Book {
fn age(&self, current_year: u32) -> u32 {
current_year - self.published_year
}
}
fn main() {
let author1 = Author {
name: String::from("J.K. Rowling"),
birth_year: 1965,
};
let book1 = Book {
title: String::from("Harry Potter and the Philosopher's Stone"),
author: author1,
published_year: 1997,
};
println!("Book '{}' is {} years old.", book1.title, book1.age(2025));
}
هذا المثال يوضح كيف يمكن تنظيم بيانات معقدة عبر هياكل متداخلة، ويظهر أيضًا كيف يمكن ربط دوال بحساب معلومات متعلقة.
مقارنة بين الهياكل والأنواع الأخرى في رست
في رست توجد عدة طرق لتعريف أنواع معقدة، منها:
-
الهياكل (Structs): تُستخدم لتنظيم البيانات مع حقول مختلفة بأسماء وأنواع مختلفة.
-
الأنماط (Enums): تُستخدم لتعريف نوع يمكن أن يكون أحد عدة أشكال مختلفة، مفيدة لتمثيل حالات متغيرة.
-
النوع Tuple: يُستخدم لمجموعة من القيم المرتبة.
كل نوع له استخدامه الخاص، لكن الهياكل هي الأكثر شيوعًا لتنظيم البيانات ذات الخصائص المتعددة والواضحة.
التعامل مع الهياكل في البرمجة المتزامنة (Concurrency)
رست تقدم نظام أمان متقدم يسمح باستخدام الهياكل بأمان في بيئات البرمجة المتزامنة، وذلك عبر قواعد الاقتراض والملكية التي تمنع حدوث مشاكل مثل التداخل (Race Conditions) والتسربات.
يمكن استخدام الهياكل داخل Arc أو Mutex لتوفير مشاركة آمنة بين خيوط التنفيذ المختلفة:
rustuse std::sync::{Arc, Mutex};
use std::thread;
struct Counter {
value: u32,
}
fn main() {
let counter = Arc::new(Mutex::new(Counter { value: 0 }));
let mut handles = vec![];
for _ in 0..10 {
let counter = Arc::clone(&counter);
let handle = thread::spawn(move || {
let mut num = counter.lock().unwrap();
num.value += 1;
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap();
}
println!("Result: {}", counter.lock().unwrap().value);
}
خلاصة استخدام الهياكل في رست
تمثل الهياكل في رست الركيزة الأساسية لتنظيم البيانات وتشكيل أنواع معقدة وذات دلالة واضحة. تتسم هذه الهياكل بالقوة والمرونة من حيث تعريف البيانات، ربط السلوكيات، التداخل، التوافق مع نظام الملكية والاقتراض، وأمان البرمجة المتزامنة.
يُعد فهم كيفية استخدام الهياكل بدقة من المهارات الضرورية لأي مبرمج يريد استغلال إمكانيات رست بالكامل، وذلك لإنشاء برمجيات قوية، آمنة، وذات أداء عالٍ.
جدول ملخص لأنواع الهياكل في رست
| نوع الهيكل | الوصف | استخدام شائع | مثال |
|---|---|---|---|
| Named Fields Struct | هيكل يحتوي على حقول مسماة بأنواع مختلفة | تمثيل بيانات مركبة واضحة | struct Person { name: String, age: u32 } |
| Tuple Struct | هيكل بدون أسماء للحقول، فقط مواقع | تمثيل بيانات بسيطة متعددة الأجزاء | struct Color(u8, u8, u8); |
| Unit Struct | هيكل بدون حقول | تعريف نوع كعلامة أو لتحديد سلوك معين | struct Marker; |
مصادر ومراجع
-
The Rust Programming Language, Steve Klabnik and Carol Nichols, 2018.
-
Rust By Example, https://doc.rust-lang.org/rust-by-example/structs.html
يُعد التمكن من مفهوم الهياكل في رست وتطبيقاتها المتعددة أساسًا مهمًا لبناء أنظمة برمجية معقدة، مما يعزز من فاعلية الأداء مع ضمان أمان البيانات وإدارتها بمرونة عالية.

