البروتوكولات في Swift: كيفية تعريف الطرق الاختيارية (دليل كامل)
\n\nهل سبق لك أن كتبت بروتوكولًا في Swift وأردت جعل إحدى الطرق اختيارية؟ بحيث يمكن للفئة التي تتبنى البروتوكول عدم تنفيذ هذه الطريقة، ولا يشتكي المترجم؟ إذا كان الأمر كذلك - فأنت لست وحدك. هذا السؤال من Stack Overflow حصد آلاف المشاهدات، واليوم سنفهم مرة وإلى الأبد كيف تعمل الطرق الاختيارية في بروتوكول Swift.
\n\nلكن هناك فارق بسيط: Swift هي لغة ذات كتابة صارمة، ولا توجد طرق اختيارية "نقية" فيها. لكن هناك عدة طرق أنيقة للالتفاف حول ذلك. سنستعرض كل منها، مع أمثلة كود، لتتمكن من اختيار الأنسب لمشروعك.
\n\nلماذا لا تحب Swift الطرق الاختيارية؟
\n\nفي Objective-C، كان بإمكان البروتوكولات وضع علامة على الطرق كـ @optional، وكان كل شيء يعمل. أما Swift فقد صُمم منذ البداية مع التركيز على الأمان. إذا أعلن البروتوكول عن طريقة - فهذا يعني أن أي فئة تتبناه ملزمة بتنفيذها. وإلا - خطأ في الترجمة. هذا رائع لأنك لن تنسى تنفيذ طريقة مهمة، ويصبح الكود قابلاً للتوقع.
لكن في الحياة الواقعية، غالبًا ما نحتاج إلى: "نفذ الطريقة إذا أردت، وإلا فاستخدم السلوك الافتراضي". ماذا نفعل؟ هناك ثلاث طرق رئيسية.
\n\nالطريقة 1: @objc و optional (تقليدية، ولكن مع تحفظات)
\n\nأقدم وأبسط طريقة هي استخدام السمة @objc. فهي تنقل البروتوكول إلى عالم Objective-C runtime، حيث توجد الطرق الاختيارية "جاهزة".
import Foundation\n\n@objc protocol DataSource {\n @objc optional func fetchData() -> [String]\n func mandatoryMethod()\n}\n\nclass MyViewController: UIViewController, DataSource {\n func mandatoryMethod() {\n print("تم تنفيذ الطريقة الإلزامية")\n }\n // fetchData() يمكن عدم تنفيذها\n}\n\n// الاستخدام:\nlet vc = MyViewController()\nvc.fetchData?() // استدعاء آمن - لن يحدث شيء\nvc.mandatoryMethod()\n\nالإيجابيات: البساطة، بناء جملة واضح، يعمل مع المفوضيات.
\nالسلبيات:
\n- \n
- يمكن استخدام البروتوكول فقط مع الفئات (وليس الهياكل أو التعدادات). \n
- يجب وضع علامة
@objcعلى البروتوكول بأكمله. \n - تفقد بعض الإمكانيات الخاصة بـ Swift (الأنواع المرتبطة، شروط where). \n
هذا الخيار مثالي إذا كنت تكتب لنظام iOS/macOS وتعمل مع UIKit (مثل مفوضيات UITableView). لكن بالنسبة لكود Swift الخالص، من الأفضل استخدام طرق أخرى.
\n\nالطريقة 2: امتدادات البروتوكول مع تنفيذ افتراضي (موصى به)
\n\nهذه هي الطريقة الأكثر توافقًا مع Swift. تعلن عن بروتوكول بطرق إلزامية، ثم في الامتداد تعطي تنفيذًا "افتراضيًا" للطرق التي تريد جعلها اختيارية.
\n\nprotocol Configurable {\n func configureUI()\n func setupBindings() // نريد جعلها اختيارية\n}\n\nextension Configurable {\n func setupBindings() {\n // تنفيذ افتراضي فارغ\n print("لم يتم تكوين الارتباطات (تم استخدام التنفيذ القياسي)")\n }\n}\n\nclass MyView: Configurable {\n func configureUI() {\n print("تم تكوين الواجهة")\n }\n // setupBindings() يمكن عدم كتابتها - سيتم استخدام التنفيذ من الامتداد\n}\n\nclass AdvancedView: Configurable {\n func configureUI() {\n print("واجهة متقدمة")\n }\n func setupBindings() {\n print("ارتباطات خاصة")\n }\n}\n\nlet view = MyView()\nview.setupBindings() // سيظهر: "لم يتم تكوين الارتباطات (تم استخدام التنفيذ القياسي)"\n\nlet advanced = AdvancedView()\nadvanced.setupBindings() // سيظهر: "ارتباطات خاصة"\n\nلماذا هذا رائع؟
\n- \n
- يعمل مع الفئات والهياكل والتعدادات. \n
- أصلي تمامًا في Swift، بدون objc.