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

الكلمة المفتاحية final Class

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

أحياناً قد ترغب في منع فئة (class) من أن يتم توسيعها. الكلمة المفتاحية final، عند تطبيقها على فئة، تمنع أي فئة أخرى من الوراثة منها.

final class DatabaseConnection {
  String connectionString;
  
  DatabaseConnection(this.connectionString);
  
  void connect() {
    print('Connected to $connectionString');
  }
}

// سيؤدي هذا إلى حدوث خطأ في وقت الترجمة:
// class CustomConnection extends DatabaseConnection { }

يعد تمييز الفئة كـ final مفيداً عندما يكون توسيعها قد يؤدي إلى كسر سلوكها المقصود أو ضمانات الأمان الخاصة بها. على سبيل المثال، قد تحتاج الفئة التي تدير موارد حساسة إلى التأكد من عدم تجاوز دوالها (methods) بطرق غير متوقعة.

قدمت Dart 3 أيضًا معدلات ذات صلة: يجبر base الفئات الفرعية على استخدام extends (وليس implements)، ويقيد sealed الوراثة لنفس المكتبة. في الوقت الحالي، ركز على final باعتبارها أبسط طريقة لإغلاق فئة تمامًا.

استخدم الأصناف final عندما تكون متأكداً من أن تصميم الصنف مكتمل وأن الوراثة لن تسبب إلا المشاكل. ومع ذلك، لا تبالغ في استخدامه - فمعظم الأصناف تستفيد من بقائها مفتوحة للتوسعة.

challenge icon

التحدي

سهل

لنقم ببناء نظام تكوين (configuration) آمن يوضح متى ولماذا قد ترغب في منع وراثة فئة (class) معينة. ستقوم بإنشاء فئة نهائية (final class) تدير إعدادات التطبيق، مما يضمن عدم إمكانية تغيير سلوكها من خلال الوراثة.

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

  • config.dart: قم بتعريف فئات التكوين الخاصة بك هنا:
    • final class AppConfig لا يمكن وراثتها. يجب أن تحتوي على خاصية String appName و String version، ومنشئ (constructor) يأخذ كلتا القيمتين، وتابع (method) باسم display() يطبع [appName] v[version]
    • فئة Feature عادية (غير نهائية) تحتوي على خاصية String name و bool enabled، ومنشئ لكليهما، وتابع status() يطبع [name]: [enabled ? 'ON' : 'OFF']
    • فئة ExperimentalFeature ترث من Feature وتضيف خاصية String warning. قم بإعادة تعريف status() باستخدام @override لاستدعاء نسخة الأب أولاً باستخدام super.status()، ثم طباعة Warning: [warning]
  • main.dart: قم باستيراد ملف التكوين الخاص بك واستعرض الفرق بين الفئات النهائية والعادية:
    • أنشئ كائن AppConfig بقيمة appName هي 'MyApp' وإصدار '2.0.1'، ثم استدعِ display()
    • اطبع سطراً فارغاً
    • أنشئ كائن Feature باسم 'Dark Mode' وقيمة enabled هي true، ثم استدعِ status()
    • اطبع سطراً فارغاً
    • أنشئ كائن ExperimentalFeature باسم 'AI Assistant'، وقيمة enabled هي false، وتحذير 'May be unstable'، ثم استدعِ status()

لاحظ كيف تم تمييز AppConfig بكلمة final لأن سلوك التكوين الخاص بها يجب أن يظل ثابتاً وآمناً - لا ينبغي لأي فئة فرعية أن تكون قادرة على تغيير كيفية إدارة الإعدادات. وفي الوقت نفسه، تظل Feature مفتوحة للتوسيع، مما يسمح لـ ExperimentalFeature بإضافة سلوك متخصص.

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

MyApp v2.0.1

Dark Mode: ON

AI Assistant: OFF
Warning: May be unstable

ورقة مرجعية

تمنع الكلمة الأساسية final توريث الفئة (class):

final class DatabaseConnection {
  String connectionString;
  
  DatabaseConnection(this.connectionString);
  
  void connect() {
    print('Connected to $connectionString');
  }
}

// سيؤدي هذا إلى خطأ في وقت التجميع:
// class CustomConnection extends DatabaseConnection { }

استخدم فئات final عندما يكون توريثها قد يؤدي إلى كسر السلوك المقصود أو الضمانات الأمنية. يجب أن تظل معظم الفئات مفتوحة للتوسيع ما لم يكن هناك سبب محدد لتقييدها.

يوفر Dart 3 أيضًا المعدلات base (التي تجبر الفئات الفرعية على استخدام extends) و sealed (التي تقيد الوراثة في نفس المكتبة).

جرّب بنفسك

import 'config.dart';

void main() {
  // TODO: أنشئ AppConfig بـ appName 'MyApp' و version '2.0.1'
  // ثم استدعِ display()
  
  // TODO: اطبع سطرًا فارغًا
  
  // TODO: أنشئ Feature بـ name 'Dark Mode' و enabled true
  // ثم استدعِ status()
  
  // TODO: اطبع سطرًا فارغًا
  
  // TODO: أنشئ ExperimentalFeature بـ name 'AI Assistant'،
  // و enabled false، و warning 'May be unstable'
  // ثم استدعِ status()
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming