البروتوكولات في Swift: كيفية تعريف الطرق الاختيارية (تحليل كامل)

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

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

ابدأ الدورة

البروتوكولات في Swift: كيفية تعريف الطرق الاختيارية (دليل كامل)

\n\n

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

\n\n

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

\n\n

لماذا لا تحب Swift الطرق الاختيارية؟

\n\n

في Objective-C، كان بإمكان البروتوكولات وضع علامة على الطرق كـ @optional، وكان كل شيء يعمل. أما Swift فقد صُمم منذ البداية مع التركيز على الأمان. إذا أعلن البروتوكول عن طريقة - فهذا يعني أن أي فئة تتبناه ملزمة بتنفيذها. وإلا - خطأ في الترجمة. هذا رائع لأنك لن تنسى تنفيذ طريقة مهمة، ويصبح الكود قابلاً للتوقع.

\n\n

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

\n\n

الطريقة 1: @objc و optional (تقليدية، ولكن مع تحفظات)

\n\n

أقدم وأبسط طريقة هي استخدام السمة @objc. فهي تنقل البروتوكول إلى عالم Objective-C runtime، حيث توجد الطرق الاختيارية "جاهزة".

\n\n
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
\n\n

هذا الخيار مثالي إذا كنت تكتب لنظام iOS/macOS وتعمل مع UIKit (مثل مفوضيات UITableView). لكن بالنسبة لكود Swift الخالص، من الأفضل استخدام طرق أخرى.

\n\n

الطريقة 2: امتدادات البروتوكول مع تنفيذ افتراضي (موصى به)

\n\n

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

\n\n
protocol 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.

المدونات

توصيات الكتب