Struct vs Class في Swift: متى ولماذا نختار الهيكل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

Struct أم Class؟ السؤال الأبدي لمطور Swift

\n\n

كل من يبدأ في البرمجة بلغة Swift، عاجلاً أم آجلاً، يواجه هذا السؤال. يبدو أن كلا التركيبين يسمحان بإنشاء كائنات تحتوي على بيانات وطرق. ولكن لماذا يحصل هذا السؤال على آلاف المشاهدات على Stack Overflow، ولماذا يفضل المطورون ذوو الخبرة الهياكل بشكل متزايد؟

\n\n

الإجابة بسيطة: لأن الاختيار بين struct و class يؤثر بشكل مباشر على الأداء، وسلامة الخيوط، وهندسة تطبيقك. في هذه المقالة، سنناقش ليس فقط النظرية، بل أمثلة حقيقية وسيناريوهات حيث يتفوق Struct بشكل قاطع على Class.

\n\n
\nإذا كنت تكتب بلغة Swift وما زلت تستخدم الفئات "بدافع العادة" من Objective-C — فهذه المقالة لك. استعد لإعادة التفكير في أساليبك.\n
\n\n

الفرق الرئيسي: Value Type vs Reference Type

\n\n

قبل التعمق في التفاصيل، دعنا نتذكر الفرق الأساسي:

\n\n
    \n
  • Struct هو value type (نوع قيمة). عند التعيين أو التمرير إلى دالة، يتم إنشاء نسخة من البيانات.
  • \n
  • Class هو reference type (نوع مرجعي). عند التعيين أو التمرير إلى دالة، يتم تمرير مرجع إلى نفس الكائن في الذاكرة.
  • \n
\n\n

يبدو الأمر بسيطًا. ولكن من هذا الاختلاف "الذري" تنشأ جميع العواقب التي سنناقشها الآن.

\n\n

مثال 1: سلوك غير متوقع للـ Class

\n\n
class PersonClass {\n    var name: String\n    init(name: String) {\n        self.name = name\n    }\n}\n\nstruct PersonStruct {\n    var name: String\n}\n\n// اختبار الكلاس\nlet person1 = PersonClass(name: "آنا")\nlet person2 = person1\nperson2.name = "ماريا"\n\nprint(person1.name) // ماريا! تغيرت أيضًا في person1\nprint(person2.name) // ماريا\n
\n\n

هل لاحظت المشكلة؟ بتغيير الاسم في person2، قمنا بتغييره أيضًا في person1 دون قصد. لأنهما نفس الكائن في الذاكرة. في مثال صغير، هذا ليس خطيرًا، ولكن في مشروع حقيقي، يمكن أن يؤدي هذا "التغيير الجانبي" إلى أخطاء يصعب تتبعها.

\n\n
// اختبار الهيكل\nvar person3 = PersonStruct(name: "آنا")\nvar person4 = person3\nperson4.name = "ماريا"\n\nprint(person3.name) // آنا! كل شيء في مكانه\nprint(person4.name) // ماريا\n
\n\n

يتصرف الهيكل بشكل متوقع: كل متغير يمتلك نسخة مستقلة خاصة به من البيانات. هذا آمن وواضح.

\n\n

متى يكون Struct هو الاختيار الواضح؟

\n\n

توصي Apple في وثائقها باستخدام struct بشكل افتراضي. دعنا نذكر السيناريوهات المحددة التي يتفوق فيها الهيكل بلا منازع.

\n\n

1. البيانات التي يجب أن تكون غير قابلة للتغيير

\n\n

إذا كنت تعمل مع نماذج لا يجب أن تتغير بعد الإنشاء (مثل نتائج استعلام إلى خادم)، فإن struct مع خصائص ثابتة هو الخيار المثالي.

\n\n
struct UserProfile {\n    let id: Int\n    let name: String\n    let email: String\n}\n\n// أنشأناها — ونسيناها. البيانات محمية من التغييرات العرضية.\nlet profile = UserProfile(id: 1, name: "إيفان", email: "ivan@example.com")\n
\n\n

مع الكلاس، كان بإمكانك تغيير name عن طريق الخطأ إذا كانت الخاصية مُعلنة كـ var. مع الهيكل، يجبرك المترجم على التفكير في الثبات.

\n\n

2. الكيانات الصغيرة والمستقلة

\n\n

إذا كان نموذجك يصف شيئًا بسيطًا — إحداثيات، أبعاد، لون، مبلغ مالي — استخدم struct. هذا منطقي وفعال.

\n\n
struct Point {\n    var x: Double\n    var y: Double\n}\n\nstruct Money {\n    var amount: Double\n    var currency: String\n}\n\nstruct Rectangle {\n    var origin: Point\n    var size: Size\n}\n
\n\n

هذه الأنواع لا تحتاج إلى وراثة أو إدارة مراجع. إنها ببساطة

المدونات

توصيات الكتب