تظليل متغير
في برمجة الحاسوب ، يحدث تداخل المتغيرات عندما يحمل متغير مُعلن ضمن نطاق معين (كتلة قرار، أو دالة، أو فئة داخلية ) نفس اسم متغير مُعلن في نطاق خارجي. على مستوى المعرفات (الأسماء، وليس المتغيرات)، يُعرف هذا بإخفاء الاسم . يُقال إن المتغير الخارجي مُغطى بالمتغير الداخلي، بينما يُقال إن المعرف الداخلي يُخفي المعرف الخارجي. قد يُؤدي هذا إلى التباس، إذ قد لا يكون واضحًا إلى أي متغير تُشير الاستخدامات اللاحقة لاسم المتغير المُغطى، وهو ما يعتمد على قواعد تحليل الأسماء في لغة البرمجة.
كانت لغة ALGOL من أوائل اللغات التي أدخلت خاصية التظليل المتغير ، حيث قدمت لأول مرة الكتل لتحديد النطاقات. وقد سمحت بذلك أيضاً العديد من لغات البرمجة المشتقة منها، بما في ذلك C و C++ و Java .
لغة C# تكسر هذا التقليد، حيث تسمح بتظليل المتغيرات بين فئة داخلية وفئة خارجية، وبين طريقة وفئة تحتوي عليها، ولكن ليس بين كتلة if وطريقة تحتوي عليها، أو بين عبارات الحالة في كتلة switch .
تسمح بعض اللغات بتظليل المتغيرات في حالات أكثر من غيرها. على سبيل المثال ، تسمح لغة Kotlin بتظليل متغير داخلي في دالة لمتغير مُمرَّر، وتظليل متغير في كتلة داخلية لمتغير آخر في كتلة خارجية، بينما لا تسمح لغة Java بذلك (انظر المثال أدناه ). تسمح كلتا اللغتين بتظليل حقل فئة لمتغير مُمرَّر إلى دالة/طريقة. [ 1 ]
تمنع بعض اللغات تظليل المتغيرات تمامًا مثل CoffeeScript [ 2 ] و V (Vlang) [ 3 ] .
مثال
لغة لوا
يوفر كود Lua التالي مثالاً على تظليل المتغيرات، في كتل متعددة.
v = 1 -- متغير عامdo local v = v + 1 -- متغير محلي جديد يُخفي المتغير العام v print ( v ) -- يطبع 2do local v = v * 2 -- متغير محلي آخر يُخفي المتغير المحلي الخارجي v print ( v ) -- يطبع 4 endprint ( v ) -- يطبع 2 endprint ( v ) -- يطبع 1بايثون
يُقدّم كود بايثون التالي مثالاً آخر على تظليل المتغيرات:
x = 0def outer (): x = 1def inner (): x = 2 print ( "inner:" , x )inner () print ( "outer:" , x )outer () print ( "global: " , x )مطبوعات داخلي: 2 خارجي: 1 عام: 0بما أنه لا يوجد تعريف للمتغيرات في بايثون وإنما فقط تعيين للمتغيرات، فإن الكلمة المفتاحية nonlocalالتي تم تقديمها في بايثون 3 تُستخدم لتجنب تظليل المتغيرات وتعيين القيم للمتغيرات غير المحلية:
x = 0def outer (): x = 1def inner (): nonlocal x x = 2 print ( "inner:" , x )inner () print ( "outer:" , x )outer () print ( "global: " , x )مطبوعات داخلي: 2 خارجي: 2 عام: 0تُستخدم الكلمة المفتاحية globalلتجنب تداخل المتغيرات وتعيين القيم للمتغيرات العامة:
x = 0def outer (): x = 1def inner (): global x x = 2 print ( "inner:" , x )inner () print ( "outer:" , x )outer () print ( "global: " , x )عدد الطبعات الداخلية: 2 الخارجية: 1 العالمية: 2الصدأ
fn main () { let x = 0 ; { // الظل let x = 1 ; println! ( "Inner x: {}" , x ); // يطبع 1 } println! ( "Outer x: {}" , x ); // يطبع 0 let x = "Rust" ; println! ( "Outer x: {}" , x ); // يطبع 'Rust' }//# Inner x: 1 //# Outer x: 0 //# Outer x: Rustلغة سي++
#include <iostream>int main () { int x = 42 ; int sum = 0 ;for ( int i = 0 ; i < 10 ; i ++ ) { int x = i ; std :: cout << "x: " << x << '\n' ; // يطبع قيم i من 0 إلى 9 sum += x ; }std :: cout << "sum: " << sum << '\n' ; // يطبع 45 std :: cout << "x: " << x << '\n' ; // يطبع 42return 0 ; }جافا
public class Shadow { private int myIntVar = 0 ;public void shadowTheVar () { // بما أن له نفس اسم حقل مثيل الكائن أعلاه، فإنه يحجب الحقل أعلاه // داخل هذه الطريقة. int myIntVar = 5 ;// إذا أشرنا ببساطة إلى 'myIntVar ' ، فسيتم العثور على نسخة هذه الطريقة // (تحجب نسخة ثانية بنفس الاسم) System.out.println ( myIntVar ); // يطبع 5// إذا أردنا الإشارة إلى المتغير myIntVar المُظلل من هذه الفئة، فنحن بحاجة إلى // الإشارة إليه على النحو التالي : System.out.println ( this.myIntVar ) ; // يطبع 0 }public static void main ( String [] args ){ new Shadow (). shadowTheVar (); } }لكن الكود التالي لن يتم تجميعه:
public class Shadow { public static void main ( String [] args ){ int a = 1 ;for ( int i = 0 ; i < 10 ; i ++ ) { // هذا يُسبب خطأ في الترجمة لأن إعادة تعريف متغير // داخل كتلة متداخلة في نفس الدالة غير مسموح بها . int a = i ; System.out.println ( a ) ; } } }جافا سكريبت
يسمح إدخال ECMAScript 6let مع constنطاق الكتلة بتظليل المتغيرات.
دالة myFunc () { let my_var = ' test' ; if ( true ) { let my_var = 'new test' ; console.log ( my_var ) ; // new test } console.log ( my_var ) ; // test } myFunc ( );انظر أيضاً
مراجع
- ↑ "من جافا إلى كوتلن والعودة مرة أخرى" . مؤرشف من الأصل بتاريخ 28 نوفمبر 2020. تم الاطلاع عليه بتاريخ 4 أكتوبر 2021 .
- ↑ "يرجى إضافة خاصية التظليل الصريح · المشكلة رقم 2697 · jashkenas/Coffeescript" . GitHub . مؤرشف من الأصل بتاريخ 4 أكتوبر 2021. تم الاطلاع عليه بتاريخ 4 أكتوبر 2021 .
- ↑ "توثيق لغة Vlang - "على عكس معظم اللغات، لا يُسمح بتظليل المتغيرات"" . GitHub . تم الاسترجاع في 27-06-2024 .
- متغير (علوم الحاسوب)
- مقارنات لغات البرمجة
