Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

الأصناف المختومة (Sealed Classes - Dart 3)

جزء من قسم Object Oriented Programming في رحلة Dart على Coddy — الدرس 85 من 110.

قدمت Dart 3 الفئات المختومة (sealed classes)، والتي تقيد الفئات التي يمكنها توسيعها أو تنفيذها. عندما تميز فئة بأنها sealed، فإن الفئات الموجودة في نفس الملف فقط هي التي يمكن أن تكون أنواعاً فرعية مباشرة لها. وهذا ينشئ مجموعة مغلقة من الأنواع الفرعية المعروفة.

sealed class Result {}

class Success extends Result {
  final String data;
  Success(this.data);
}

class Failure extends Result {
  final String error;
  Failure(this.error);
}

تكمن قوة الأصناف المختومة (sealed classes) في التحقق من الشمولية (exhaustiveness checking). فعندما تستخدم switch على نوع مختوم، يعرف المترجم جميع الأنواع الفرعية الممكنة ويضمن تعاملك مع كل واحد منها:

String handleResult(Result result) {
  return switch (result) {
    Success(data: var d) => 'Got: $d',
    Failure(error: var e) => 'Error: $e',
  };
  // لا حاجة لـ default - المترجم يعرف أن جميع الحالات مغطاة!
}

void main() {
  var success = Success('Hello');
  var failure = Failure('Not found');
  
  print(handleResult(success));  // تم الحصول على: Hello
  print(handleResult(failure));  // خطأ: Not found
}

إذا قمت بإضافة نوع فرعي جديد إلى sealed class، فسيقوم المترجم بتمييز كل جملة switch لا تتعامل معه. وهذا يجعل الـ sealed classes مثالية لنمذجة الحالات، أو النتائج، أو أي سيناريو يكون لديك فيه مجموعة ثابتة من المتغيرات. وعلى عكس الـ abstract classes، تضمن الـ sealed classes عدم تمكن أي كود خارجي من إضافة أنواع فرعية غير متوقعة.

challenge icon

التحدي

سهل

لنقم ببناء معالج لطلبات الشبكة باستخدام الأصناف المختومة (sealed classes)! ستقوم بإنشاء نظام آمن النوع (type-safe) يمثل الحالات المختلفة لاستجابة الشبكة، مما يضمن التعامل مع كل نتيجة محتملة بشكل صحيح.

ستقوم بتنظيم الكود الخاص بك في ملفين:

  • response.dart: قم بإنشاء تسلسل هرمي للأصناف المختومة يمثل جميع الحالات الممكنة لاستجابة الشبكة:
    • صنف مختوم يسمى NetworkResponse يعمل كقاعدة لجميع أنواع الاستجابات.
    • صنف Loading يرث من NetworkResponse مع حقل String message (على سبيل المثال، "Fetching data...").
    • صنف Success يرث من NetworkResponse مع حقل String data وحقل int statusCode.
    • صنف Error يرث من NetworkResponse مع حقل String errorMessage وحقل int errorCode.
  • main.dart: قم باستيراد ملف الاستجابة الخاص بك وأنشئ دالة تعالج جميع أنواع الاستجابات باستخدام تعبير switch:
    • أنشئ دالة handleResponse(NetworkResponse response) تعيد String.
    • استخدم تعبير switch مع مطابقة الأنماط (pattern matching) للتعامل مع كل حالة:
      • لحالة Loading: أعد Status: [message].
      • لحالة Success: أعد Success ([statusCode]): [data].
      • لحالة Error: أعد Error ([errorCode]): [errorMessage].
    • أنشئ ثلاث حالات استجابة واطبع نتيجة معالجة كل منها:
      • كائن Loading مع رسالة Please wait....
      • كائن Success مع بيانات User profile loaded ورمز حالة 200.
      • كائن Error مع رسالة خطأ Not found ورمز خطأ 404.

يكمن جمال الأصناف المختومة في أن المترجم (compiler) يضمن لك التعامل مع كل نوع استجابة محتمل - لا حاجة لحالة افتراضية (default case)!

المخرجات المتوقعة:

Status: Please wait...
Success (200): User profile loaded
Error (404): Not found

جرّب بنفسك

import 'response.dart';

// TODO: قم بإنشاء دالة handleResponse(NetworkResponse response)
// التي تُرجع String
// استخدم تعبير switch مع مطابقة الأنماط (pattern matching) للتعامل مع كل حالة:
// - لـ Loading: أرجع "Status: [message]"
// - لـ Success: أرجع "Success ([statusCode]): [data]"
// - لـ Error: أرجع "Error ([errorCode]): [errorMessage]"

void main() {
  // TODO: قم بإنشاء مثيل (instance) من Loading مع الرسالة "Please wait..."
  
  // TODO: قم بإنشاء مثيل (instance) من Success مع البيانات "User profile loaded" ورمز الحالة 200
  
  // TODO: قم بإنشاء مثيل (instance) من Error مع رسالة الخطأ "Not found" ورمز الخطأ 404
  
  // TODO: اطبع نتيجة معالجة كل استجابة (response)
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming