الأنواع الاختيارية في سويفت: كيفية استخدام Optionals وفكّها بأمان

دقائق القراءة: 7

مقدمة لفهم الأنواع الاختيارية في Swift

إذا كنت قادماً من لغات مثل Java أو C++ أو غيرها من اللغات الكائنية، فقد لا تكون صادفت من قبل مفهوم الأنواع الاختيارية أو Optionals. في لغة Swift يُعد هذا المفهوم من الأساسيات التي لا يمكن تجاهلها، لأنه يرتبط مباشرة بأمان الكود وتقليل الأخطاء وقت التشغيل.

تُستخدم الأنواع الاختيارية عندما تكون القيمة قد تكون موجودة أو غير موجودة. وبدلاً من التعامل العشوائي مع القيم الفارغة، تمنحك Swift طريقة واضحة ومنضبطة للتأكد من وجود القيمة قبل استخدامها.

شرح الأنواع الاختيارية في سويفت وكيفية استخدام Optionals وفكها بأمان

الثوابت والمتغيرات في Swift

قبل فهم Optionals، من المفيد مراجعة الفرق بين الثابت والمتغير في Swift:

  • الثابت هو قيمة لا يمكن تغييرها بعد إسنادها، ويُعرّف بالكلمة المفتاحية let.
  • المتغير هو قيمة يمكن تعديلها لاحقاً، ويُعرّف بالكلمة المفتاحية var.

الصيغة العامة للتعريف تكون كالتالي:

<data-item-type> <var-name>:<data-type> = <value>

مثال على ثابت:

let pi:Double = 3.1415

ومثال على متغير:

var message: String = "Hello, this is prajwal"
message = "Coding in swift is awesome" // variable value changed

في هذا المثال استخدمنا let لتعريف ثابت، وvar لتعريف متغير. بعد الاسم نضع النقطتين : ثم نوع البيانات، وبعدها القيمة.

الاستدلال على نوع البيانات في Swift

لغة Swift آمنة من ناحية الأنواع، كما أنها قادرة على استنتاج نوع البيانات تلقائياً في كثير من الحالات. على سبيل المثال:

let const:String = "String"

يمكن كتابتها أيضاً بالشكل التالي:

let const = "String"

وكذلك:

var speed:Int = 20

يمكن كتابتها:

var speed = 35

لكن عند التعامل مع Optionals يصبح تحديد النوع مهماً، لأن النوع الاختياري يختلف عن النوع التقليدي حتى لو كان مبنياً عليه.

ما هي الأنواع الاختيارية Optionals في Swift؟

النوع الاختياري هو نوع يسمح بوجود حالتين فقط:

  • إما أن القيمة موجودة ويمكن الوصول إليها بعد فكّها.
  • أو أن القيمة غير موجودة إطلاقاً، وتكون حينها nil.

الفكرة الجوهرية هنا أن Swift لا تتركك تستخدم قيمة قد تكون فارغة دون تحقّق مسبق، وهذا يقلل احتمالات الانهيار أثناء التشغيل.

يمكن أن يكون النوع الاختياري مبنياً على أي نوع تقريباً، مثل String أو Int أو Double أو حتى كائن مخصص. لكن من المهم فهم نقطة أساسية: النوع String? ليس هو نفسه String، والنوع Int? ليس هو نفسه Int. السبب أن النوع الأساسي لا يقبل القيمة nil، بينما النوع الاختياري يقبلها.

صيغة تعريف Optionals واستخدامها

تعريف النوع الاختياري يشبه تعريف المتغيرات العادية، لكن مع إضافة علامة الاستفهام ? بعد نوع البيانات:

<data-item> <var-name>:<data-type>?

أمثلة عملية:

let someVal: Double?
someVal = 5.6324
print(someVal) // Output: Optional(5.6324)

var str: String? = nil
str = "Hello, World!"
print(str) // Output: Optional("Hello, World!")

لاحظ أن الناتج ليس قيمة خاماً، بل قيمة مغلّفة داخل Optional. وهذا يعني أنه لا يمكنك الاعتماد عليها مباشرة في كل موضع قبل فكّها أو التحقق منها.

ما المقصود بفكّ Optional؟

فكّ النوع الاختياري أو Unwrapping يعني استخراج القيمة الداخلية من المتغير الاختياري بعد التأكد من أنها ليست nil. لا يُنصح باستخدام النوع الاختياري مباشرة في العمليات المهمة قبل هذه الخطوة.

بمعنى أبسط، أنت لا تعرف هل المتغير يحتوي على قيمة فعلية أم لا، لذلك يجب التحقق أولاً. بعد التأكد، يمكنك التعامل معه كقيمة عادية من نوعها الأساسي.

توفر Swift عدة طرق لفكّ Optionals، وأهمها:

  • التحقق عبر if-else.
  • الفك الإجباري Forced Unwrapping.
  • الربط الاختياري Optional Binding.
  • السلسلة الاختيارية Optional Chaining.
  • المعامل Nil Coalescing Operator.

فكّ Optional باستخدام if-else

هذه أبسط طريقة للتحقق مما إذا كانت القيمة تساوي nil أم لا:

var variable: String? // evaluates to nil

if variable != nil {
    print("Not nil")
} else {
    print("Nil")
}
// Output: Nil

هذه الطريقة مناسبة عندما تريد فقط معرفة ما إذا كانت القيمة موجودة، لكنها ليست الأفضل دائماً إذا كنت تريد استخدام القيمة نفسها بشكل مباشر داخل الكتلة البرمجية.

الفك الإجباري Forced Unwrapping في Swift

يتم الفك الإجباري باستخدام علامة التعجب !. هذه الطريقة تجبر Swift على استخدام القيمة الداخلية فوراً، حتى لو كانت nil. وإذا كانت فارغة فعلاً، فسيؤدي ذلك إلى خطأ وقت التشغيل.

var color: String?
print(color!) // Unexpectedly found nil while unwrapping an Optional value

color = "Black"
print(color!) // Black

لذلك يجب استخدام هذه الطريقة فقط عندما تكون واثقاً تماماً أن المتغير لن يكون nil. في المشاريع الحقيقية، الإفراط في استخدام ! قد يجعل التطبيق أكثر عرضة للأعطال.

متى يُستخدم الفك الإجباري؟

  • عندما تكون القيمة مضمونة منطقياً قبل الوصول إليها.
  • في بعض السيناريوهات المحددة داخل بيئات مضبوطة جيداً.
  • عند التعامل مع أجزاء من الكود تعرف مسبقاً أنها لن تعيد nil.

ومع ذلك، يظل استخدام الطرق الآمنة مثل if let أفضل في أغلب الحالات.

فكّ Optional باستخدام الربط الاختياري Optional Binding

يُعد الربط الاختياري من أفضل وأسلم الطرق لفك القيم الاختيارية. الفكرة هنا أن Swift تتحقق من أن القيمة ليست nil، ثم تضعها في ثابت أو متغير جديد داخل نطاق محلي.

يتم ذلك غالباً باستخدام if let:

var password: String? = "$tr0ngp@$$w0rd"

if let unwrappedPass = password {
    print("Password is \(unwrappedPass)")
    // Password is $tr0ngp@$$w0rd
}

في المثال السابق، المتغير password هو من النوع String?. وعند تنفيذ جملة if let، يتم فك القيمة وتخزينها في الثابت unwrappedPass فقط إذا كانت القيمة موجودة.

أما إذا كانت القيمة فارغة فلن تُنفذ الكتلة:

var password: String?

if let unwrap = password {
    print("value is not nil")
}

هذا الأسلوب ممتاز لأنه يجمع بين الأمان والوضوح، وهو من أكثر الأساليب استخداماً في كتابة تطبيقات Swift الاحترافية.

فكّ Optionals باستخدام السلسلة الاختيارية Optional Chaining

تُستخدم السلسلة الاختيارية عندما يكون الوصول إلى خاصية أو قيمة معينة معتمداً على سلسلة من القيم التي قد تكون كل واحدة منها اختيارية. في هذه الحالة يمكنك استخدام ? بعد كل مستوى للوصول الآمن.

إليك المثال التالي:

class ShipmentCar {
    var seats: Int?
    var quality: String?

    init(seatQty: Int) {
        seats = seatQty
    }

    func displaySeatQuality() {
        if let seatQuality = quality {
            print("The seat covering is made of: \(seatQuality)")
        }
    }
}

class CheckSeats {
    var seatExists: ShipmentCar?
}

var obj = ShipmentCar(seatQty: 4)
var obj2: CheckSeats?
obj2 = CheckSeats()
obj2?.seatExists = obj
obj2?.seatExists?.quality = "Leather"
obj.displaySeatQuality()
// Output: The seat covering is made of: Leather

ما يحدث هنا هو أن Swift تتحقق من كل حلقة في السلسلة قبل تنفيذ الإسناد:

  • هل الكائن obj2 موجود؟
  • هل الخاصية seatExists تحتوي على كائن فعلي؟
  • إذا كانت الإجابة نعم، يتم إسناد القيمة Leather إلى الخاصية quality.

هذا الأسلوب مهم جداً عند التعامل مع كائنات مترابطة أو بيانات متداخلة، لأنه يحميك من الوصول إلى قيمة غير موجودة.

ملاحظة تقنية مهمة

قد تنجح السلسلة الاختيارية من الناحية البرمجية حتى لو كان منطق البيانات غير مثالي. على سبيل المثال، إذا كان عدد المقاعد 0 فقد يتم إسناد نوع الغطاء رغم أن ذلك لا يبدو منطقياً. لذلك يجب التمييز بين صحة الكود وصحة منطق الأعمال Business Logic.

استخدام معامل الدمج مع nil أو Nil Coalescing Operator

المعامل ?? يوفّر طريقة مختصرة وأنيقة للتعامل مع القيم الاختيارية. فإذا كانت القيمة موجودة تُستخدم كما هي، وإذا كانت nil تُستخدم قيمة افتراضية بدلاً منها.

var text: String?
var output = text ?? "Default value"
print(output) // Default value

text = "This is a string"
output = text ?? "Default String"
print(output) // This is a string

هذا الأسلوب مفيد جداً عند عرض النصوص، أو التعامل مع المدخلات الناقصة، أو تعيين قيم افتراضية للكائنات والخصائص.

متى يكون ?? هو الخيار الأفضل؟

  • عند الحاجة إلى قيمة بديلة سريعة وواضحة.
  • عند تقليل عدد شروط if-else في الكود.
  • عند تحسين قراءة الكود دون التضحية بالأمان.

أفضل الممارسات عند التعامل مع Optionals في Swift

  • استخدم Optional Binding كلما احتجت إلى الوصول الآمن للقيمة.
  • تجنب الفك الإجباري ! إلا عند الضرورة القصوى.
  • استفد من Optional Chaining عند التعامل مع كائنات مترابطة.
  • استخدم ?? عندما تكون لديك قيمة افتراضية منطقية.
  • احرص على أن يكون استخدام Optionals جزءاً من تصميم البيانات، لا مجرد حل مؤقت للأخطاء.

لماذا تُعد Optionals مهمة للمطورين؟

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

الخلاصة التقنية

الأنواع الاختيارية Optionals في Swift ليست مجرد تفصيل جانبي، بل هي من أهم مفاهيم اللغة على الإطلاق. فهمك لطريقة تعريفها وفكّها باستخدام if let أو ? أو ?? يمنحك قدرة أكبر على كتابة كود آمن ومنظّم وقابل للصيانة. ومن الناحية التقنية، أفضل نهج عملي هو تقليل الاعتماد على الفك الإجباري ! واستخدام أساليب الفك الآمنة كلما أمكن، لأن ذلك ينعكس مباشرة على استقرار التطبيق وسهولة تطويره.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *