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

الـ Static Methods والحقول

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

الآن بعد أن فهمت الفرق بين أعضاء المثيل (instance) والأعضاء الساكنة (static)، دعنا نستكشف كيفية استخدام الأساليب والحقول الساكنة بفعالية. فالأعضاء الساكنة مثالية للوظائف التي تنتمي إلى مفهوم الفئة (class) نفسه بدلاً من الكائنات الفردية.

تخزن الحقول الساكنة (Static fields) البيانات المشتركة عبر جميع المثيلات. وتشمل الاستخدامات الشائعة العدادات، أو قيم التكوين، أو البيانات المخزنة مؤقتًا:

class MathHelper {
  static const double pi = 3.14159;
  static int calculationCount = 0;
  
  static double circleArea(double radius) {
    calculationCount++;
    return pi * radius * radius;
  }
}

print(MathHelper.circleArea(5));  // 78.53975
print(MathHelper.circleArea(3));  // 28.27431
print(MathHelper.calculationCount);  // 2

لاحظ أنك تستدعي الأساليب الثابتة (static methods) مباشرة على اسم الفئة، وليس على مثيل (instance). تعمل الفئة MathHelper كأداة مساعدة - لن تحتاج أبداً إلى إنشاء كائن MathHelper.

قاعدة مهمة: لا يمكن للدوال الساكنة (static methods) الوصول إلى أعضاء الكائن (instance members) مباشرة. ليس لديها وصول إلى this لأنها غير مرتبطة بأي كائن محدد:

class Counter {
  int value = 0;  // حقل مثيل (Instance field)
  static int total = 0;  // حقل ثابت (Static field)
  
  void increment() {
    value++;  // صحيح - دالة مثيل تصل إلى حقل مثيل
    total++;  // صحيح - دالة مثيل يمكنها الوصول إلى حقل ثابت
  }
  
  static void reset() {
    total = 0;  // صحيح - دالة ثابتة تصل إلى حقل ثابت
    // value = 0;  // خطأ! لا يمكن الوصول إلى حقل مثيل
  }
}

استخدم الأعضاء الساكنة (static members) عندما لا تعتمد الوظيفة على حالة الكائن (object state) - وتعد الدوال المساعدة (utility functions) أو تتبع المصنع (factory tracking) أو الثوابت المشتركة (shared constants) خيارات مثالية لذلك.

challenge icon

التحدي

سهل

لنقم ببناء فئة أدوات (utility class) لعمليات السلاسل النصية توضح كيفية عمل الأساليب (methods) والحقول (fields) الثابتة (static) معاً لتوفير وظائف مفيدة دون الحاجة إلى إنشاء كائنات (objects).

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

  • string_utils.dart: قم بتعريف فئة StringUtils التي تعمل كمساعد أدوات. يجب أن تحتوي الفئة الخاصة بك على:
    • static const String defaultSeparator مضبوط على '-'
    • static int operationCount يبدأ بـ 0 لتتبع عدد العمليات التي تم إجراؤها
    • أسلوب ثابت reverse(String text) يقوم بزيادة operationCount وإرجاع السلسلة النصية معكوسة
    • أسلوب ثابت join(String first, String second) يقوم بزيادة operationCount وإرجاع السلسلتين النصيتين مدموجتين باستخدام defaultSeparator
    • أسلوب ثابت countVowels(String text) يقوم بزيادة operationCount وإرجاع عدد الحروف المتحركة (a, e, i, o, u - غير حساسة لحالة الأحرف)
    • أسلوب ثابت getStats() يرجع سلسلة نصية توضح إجمالي العمليات التي تم إجراؤها
  • main.dart: قم باستيراد فئة الأدوات الخاصة بك واستخدم أساليبها الثابتة:
    • استدعِ reverse() مع 'hello' واطبع النتيجة
    • استدعِ join() مع 'dart' و 'lang' واطبع النتيجة
    • استدعِ countVowels() مع 'Programming' واطبع Vowels: [count]
    • اطبع الإحصائيات باستخدام getStats()

تذكر استدعاء جميع الأساليب مباشرة على اسم الفئة لأنها ثابتة (static) - لن تقوم بإنشاء أي كائنات من StringUtils.

يجب أن يرجع الأسلوب getStats() بهذا التنسيق:

Operations performed: [operationCount]

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

olleh
dart-lang
Vowels: 3
Operations performed: 3

ورقة مرجعية

تنتمي الأعضاء الساكنة (Static members) إلى الفئة نفسها بدلاً من الحالات الفردية. قم بالوصول إليها باستخدام اسم الفئة، وليس الكائن.

تخزن الحقول الساكنة (Static fields) البيانات المشتركة عبر جميع الحالات:

class MathHelper {
  static const double pi = 3.14159;
  static int calculationCount = 0;
  
  static double circleArea(double radius) {
    calculationCount++;
    return pi * radius * radius;
  }
}

print(MathHelper.circleArea(5));  // 78.53975
print(MathHelper.calculationCount);  // 1

قواعد الوصول:

  • يمكن لأساليب الحالة (Instance methods) الوصول إلى كل من أعضاء الحالة والأعضاء الساكنة
  • يمكن للأساليب الساكنة (Static methods) الوصول فقط إلى الأعضاء الساكنة (لا يمكن الوصول إلى this)
class Counter {
  int value = 0;  // حقل حالة
  static int total = 0;  // حقل ساكن
  
  void increment() {
    value++;  // صحيح - أسلوب حالة يصل إلى حقل حالة
    total++;  // صحيح - أسلوب حالة يمكنه الوصول إلى حقل ساكن
  }
  
  static void reset() {
    total = 0;  // صحيح - أسلوب ساكن يصل إلى حقل ساكن
    // value = 0;  // خطأ! لا يمكن الوصول إلى حقل الحالة
  }
}

استخدم الأعضاء الساكنة للوظائف المساعدة، أو الثوابت المشتركة، أو العدادات، أو الوظائف التي لا تعتمد على حالة الكائن.

جرّب بنفسك

import 'string_utils.dart';

void main() {
  // TODO: استدعِ ()reverse مع 'hello' واطبع النتيجة
  
  // TODO: استدعِ ()join مع 'dart' و 'lang' واطبع النتيجة
  
  // TODO: استدعِ ()countVowels مع 'Programming' واطبع "Vowels: [count]"
  
  // TODO: اطبع الإحصائيات باستخدام ()getStats
}
quiz iconاختبر نفسك

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

جميع دروس Object Oriented Programming