📘 Class Attributes في الجافا: فهم المتغيرات المشتركة للكائنات

اليوم سنتعرف على مفهوم مهم جداً في البرمجة كائنية التوجه (OOP) وهو Class Attributes أو سمات الفئة. تخيل أنك تنشئ برنامجاً لإدارة مدرسة، وتريد تتبع عدد الطلاب المسجلين الإجمالي. هل ستقوم بحسابه يدوياً لكل كائن طالب؟ بالطبع لا! هنا يأتي دور سمات الفئة. 🎯

Class Attributes (وتسمى أيضاً Class Variables أو Static Variables) هي متغيرات تنتمي إلى الفئة نفسها، وليس إلى أي كائن (Object) محدد من هذه الفئة. هذا يعني أن جميع الكائنات المنشئة من نفس الفئة تشارك نفس القيمة لهذا المتغير.


🔍 الفرق بين Instance Variables و Class Attributes

لفهم الفكرة بشكل أوضح، دعنا نقارن بين نوعين من المتغيرات داخل الفئة:

  1. متغيرات الكائن (Instance Variables): هي المتغيرات العادية التي نعرفها. كل كائن له نسخة خاصة به منها. إذا غيرت قيمتها في كائن واحد، لا تتأثر الكائنات الأخرى.
  2. سمات الفئة (Class Attributes): هي متغيرات مشتركة بين جميع الكائنات. إذا غيرت قيمتها من خلال أي كائن (أو من خلال الفئة مباشرة)، فإن التغيير ينعكس على جميع الكائنات الأخرى.
public class Student {
    // Instance Variable
    String name;

    // Class Attribute
    static int studentCount = 0;

    public Student(String studentName) {
        name = studentName;
        studentCount++; // نزيد العداد بمقدار 1 عند إنشاء أي طالب جديد
    }
}

🔑 الكلمة المفتاحية static

لإنشاء Class Attribute، نستخدم الكلمة المفتاحية static قبل تعريف نوع المتغير. هذه الكلمة هي التي تخبر المترجم (Compiler) أن هذا المتغير ينتمي للفئة ككل.

public class Car {
    // Class Attribute: سمة فئة
    static String manufacturer = "Codex Motors";

    // Instance Variable: متغير كائن
    String model;
    String color;
}

في المثال أعلاه، افترضنا أن جميع السيارات من فئة Car تصنعها شركة واحدة ("Codex Motors"). لذلك جعلنا manufacturer سمة فئة مشتركة. أما الموديل واللون، فكل سيارة لها قيمتها الخاصة، لذا فهما متغيرا كائن عاديين.


⚡ كيفية الوصول إلى Class Attributes

يمكننا الوصول إلى سمات الفئة بطريقتين، وهذه ميزة كبيرة:

  1. من خلال اسم الفئة مباشرة (الطريقة المفضلة والأوضح):

    System.out.println(Car.manufacturer); // طباعة: Codex Motors
    
  2. من خلال أي كائن (Object) من هذه الفئة:

    Car myCar = new Car();
    myCar.model = "X200";
    System.out.println(myCar.manufacturer); // طباعة: Codex Motors أيضًا!
    

ملاحظة مهمة: على الرغم من إمكانية الوصول عبر الكائن، فإن الطريقة الموصى بها هي الوصول عبر اسم الفئة مباشرة (Car.manufacturer) لأنها توضح بشكل صريح أننا نتعامل مع متغير مشترك وليس خاصاً بكائن معين.


💡 مثال عملي شامل: عداد المنتجات

لنطبق ما تعلمناه في مثال واقعي. سننشئ فئة Product تمثل منتجاً في متجر إلكتروني. نريد أن يحتفظ البرنامج بعدد المنتجات الإجمالي الذي تم إنشاؤه.

public class Product {
    // Class Attribute: عداد المنتجات الإجمالي
    static int totalProducts = 0;

    // Instance Variables: خصائص كل منتج على حدة
    String name;
    double price;

    // Constructor
    public Product(String productName, double productPrice) {
        name = productName;
        price = productPrice;
        totalProducts++; // عند إنشاء منتج جديد، نزيد العداد
        System.out.println("تم إنشاء منتج جديد: " + name);
        System.out.println("العدد الإجمالي للمنتجات الآن: " + Product.totalProducts);
    }

    public static void main(String[] args) {
        Product p1 = new Product("لابتوب", 3000.00);
        Product p2 = new Product("هاتف", 1500.00);
        Product p3 = new Product("سماعات", 200.00);

        // يمكننا الوصول للعداد من الفئة مباشرة
        System.out.println("✅ العدد النهائي للمنتجات في النظام: " + Product.totalProducts);
    }
}

مخرجات الكود:

تم إنشاء منتج جديد: لابتوب
العدد الإجمالي للمنتجات الآن: 1
تم إنشاء منتج جديد: هاتف
العدد الإجمالي للمنتجات الآن: 2
تم إنشاء منتج جديد: سماعات
العدد الإجمالي للمنتجات الآن: 3
✅ العدد النهائي للمنتجات في النظام: 3

كما ترى، المتغير totalProducts يزيد بقيمة 1 في كل مرة ننشئ فيها كائن Product جديد، ويحتفظ بقيمته المشتركة بين جميع الكائنات.


🎯 متى نستخدم Class Attributes؟

استخدم سمات الفئة عندما تكون المعلومة:

  • مشتركة بين جميع كائنات الفئة (مثل اسم الشركة المصنعة، معدل الضريبة، عداد).
  • لا تعتمد على حالة كائن معين.
  • تحتاج إلى أن تكون قيمة واحدة يشاركها الجميع.