المتغير this في جافا

ما الذي يعنيه اِستخدَام مُعرِّف بسيط مثل amount أو process()‎ للإشارة إلى مُتْغيِّر أو تابع؟ تعتمد الإجابة بشكل أساسي على قواعد النطاق (scope rules)، والتي تُوضِح الأماكن التي يُمكِنها الوصول إلى أيّ مُتْغيِّر أو تابع قد صَرَّح عنه البرنامج وكيفية القيام بذلك.

مثلا يشير اسم المتغير البسيط داخل دالة إلى متغير محلي-متغير داخل الدالة- أو قد يشير إلى parameter وهذا في حال أن هذا التصريح عن هذا المتغير كان في نطاق scope تلك الدالة وغير ذلك فإنه يشير إلى متغير عضو-هو المتغير داخل الضنف-.

كذلك الاسم البسيط لتابع لابُدّ وأنه يُشير إلى تابع (method) مُعرَّف بنفس الصنف.

يَملُك أي عضو ساكن (static member) بصنف اسمًا بسيطًا يُمكِن اِستخدَامه داخل تعريف الصَنْف (class definition) فقط. في المقابل، يُستخدَم الاسم الكامل للعضو . للإشارة إليه من خارج الصَنْف. فمثلًا، Math.PI هو مُتْغيِّر عضو ساكن (static member variable) اسمه البسيط هو PI داخل الصنف Math. و من المُمكن دومًا الإشارة إلى أي عضو ساكن باِستخدَام اسمه الكامل حتى من داخل الصنف المُعرَّف بداخله بل قد يَكُون ذلك ضروريًا في بعض الأحيان، مثلًا عندما يَكُون الاسم البسيط للمُتغير الساكن مخفيًا نتيجة وجود مُتْغيِّر محليّ (local variable) أو مُعامِل (parameter) بنفس الاسم.

بالمثل، داخل الكائن يَملُك أي عضو نسخة (instance member) مُتْغيِّر نسخة (instance variable) أو تابع نسخة (instance method)، اسمًا بسيطًا يُمكِن اِستخدَامه بتوابع النسخ (instance methods).

تَذَكَر أن أي instance variable أو instance method هو جزء من الObject ذاته وليس ال Class التابع له , وكل كائن يَمتلك نسخة خاصة به من ذلك المُتْغيِّر أو التابع.

بالإضافة إلى الاسم البسيط-داخل الكائن-، يَملُك أي عضو نسخة (instance member) اسمًا كاملًا،

الشطر الأول من اسمه الكامل عبارة عن مَرجِع (reference) يُشير إلى الكائن المُتضمِّن لذاك ال instance member.

مثلًا، إذا كان std مُتْغيِّر يُشير إلى كائن من النوع Student، فقد تُمثِل std.test1 الاسم الكامل لمُتْغيِّر نسخة (instance variable) اسمه test1 مُعرَّف ضِمْن الكائن.

إذًا، عندما أستخدِم الاسم البسيط لinstance variable مثل test1 بداخل Class معين، أين الكائن الذي يَتَضمَّن ذلك المُتْغيِّر؟

لديك صنف Student قمت بإنشاء كائن منه هذا الكائن فيه instance method داخلها الاسم البسيط test1

هنا في هذه الحالة الاسم البسيط test1 يشير إلى ال instance variable الذي اسمه test1

هنا الكائن الذي يشير إلى ذلك المتغير قد أنشأ أثناء التنفيذ

و هذا هو السبب وراء عدم إمكانية استخدام الأسماء البسيطة لأعضاء النسخ (instance members) ضِمْن أي تابع ساكن (static methods)؛ لأنه وبينما يُنفَّذ ذلك التابع الساكن، لا يَكُون هناك أي كائن، وبالتالي لا يَكُون هناك أي أعضاء نُسخ (instance members) غالكائن غير موجود أصلاً.

المشكلة التي تحلها this ؟

اذا عرَّفت متغير عضو ثم قمت بتعريف متغير محلي بنفس اسم ذلك المتغير العضو فإن هذا المتغير المحلي يحجب المتغير العضو ضمن النطاق الذي عرف به وكذلك لو عرفت معامل صوري بنفس الاسم الخاص بالمتغير العضو فإن هذا المعامل الصوري سيحجب المتغير العضو داخل نطاقه. (راجع مفهوم التصريحات في جافا)

بعد تلك المقدمات التي ذكرت آنفاً , لاحظ المثال التالي :

public class Student {

    private String name;  // اسم الطالب

    public Student(String name) {
        // name instance = name parameter
    }
      .
      .   // المزيد من المتغيرات والتوابع
      .
}

هنا كيف كنا سنشير للعضو النسخة name بعد وجود معامل حجب ذلك المتغير.

يَضَعنا هذا أمام السؤال التالي: كيف نَستخدِم الاسم الكامل لعضو نسخة (instance members) داخل نفس الصَنْف المُعرَّف بداخله؟

تُوفِّر الجافا المُتْغيِّر الخاص this لهذا الغرض فتستطيع اِستخدَام المُتْغيِّر this للإشارة إلى نفس ذات الكائن الحاضن لنفس ذات التابع.

وبالتالي يكون حل المشكلة :

public class Student {

    private String name;  // اسم الطالب

    public Student(String name) {
       this.name = name; 
    }
      .
      .   // المزيد من المتغيرات والتوابع
      .
}

وظيفة this باختصار : ** الإشارة إلى نفس ذات الكائن الحاضن لنفس ذات التابع **وهذا يقودنا إلى أن this يستعمل في أغراض أخرى :

فعلى سبيل المثال، بينما تَكْتُب تابع نسخة (instance method)، قد تحتاج إلى تمرير الكائن الحاضن للتابع إلى برنامج فرعي (subroutine) كمُعامِل فعليّ (actual parameter). في تلك الحالة، تستطيع ببساطة تمرير this.

مثلًا، يُستخدَم System.out.println(this);‎ لطباعة تمثيل نصي (string representation) للكائن. بالإضافة إلى ذلك، قد تُسنِد this إلى مُتْغيِّر آخر ضِمْن تَعْليمَة إِسْناد (assignment statement) أو تُخزِّنه بمصفوفة. وفي العموم، تستطيع أن تَفعَل به أي شيء يُمكِنك فعله مع أي مُتْغيِّر آخر باستثناء تَعْدِيل قيمته (اِفْترِض أنه مُتْغيِّر نهائي مُعرَّف باِستخدَام المُبدِّل final).


المصدر :

كُتب في 03/11/2021