لماذا لا تحتوي Java على إعلانات متغيرة ذات نطاق كتلة؟

StackOverflow https://stackoverflow.com/questions/141140

  •  02-07-2019
  •  | 
  •  

سؤال

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

void methodName() {
  int i = 7;
  for (int j = 0; j < 10; j++) {
    int i = j * 2;
  }
}

تقريبًا كل اللغات ذات النطاق الكتلي التي استخدمتها تدعم هذا، بما في ذلك اللغات الصغيرة التافهة التي كتبت لها مترجمين فوريين ومجمعين في المدرسة.يمكن لـ Perl القيام بذلك، وكذلك Scheme، وحتى C.حتى PL/SQL يدعم هذا!

ما هو الأساس المنطقي لقرار التصميم هذا لجافا؟

يحرر:كما أشار أحدهم، جافا لديها نطاق الكتلة.ما اسم المفهوم الذي أسأل عنه؟أتمنى أن أتذكر المزيد من دروس تصميم اللغة تلك.:)

هل كانت مفيدة؟

المحلول

أعتقد أن الأساس المنطقي هو أنه في معظم الأحيان، لا يكون ذلك مقصودًا، بل يكون خللًا في البرمجة أو المنطق.

في مثال تافه مثل مثالك، يكون الأمر واضحًا، ولكن في مجموعة كبيرة من التعليمات البرمجية، قد لا يكون إعادة تعريف متغير عن طريق الخطأ أمرًا واضحًا.

الوقت المتوقع للوصول:قد يكون أيضًا مرتبطًا بمعالجة الاستثناءات في Java.اعتقدت أن جزءًا من هذا السؤال تمت مناقشته في سؤال متعلق بسبب عدم توفر المتغيرات المعلنة في قسم المحاولة في نطاقات الصيد/الأخيرة.

نصائح أخرى

حسنًا، بالمعنى الدقيق للكلمة، جافا يفعل لديها إعلانات متغيرة ذات نطاق كتلة؛لذلك هذا خطأ:

void methodName() {
  for (int j = 0; j < 10; j++) {
    int i = j * 2;
  }
  System.out.println(i); // error
}

لأن "i" غير موجود خارج الكتلة.

تكمن المشكلة في أن Java لا تسمح لك بإنشاء متغير بنفس اسم متغير آخر تم الإعلان عنه في كتلة خارجية بنفس الطريقة.كما قال أشخاص آخرون، من المفترض أن يتم ذلك لمنع الأخطاء التي يصعب التعرف عليها.

لأنه ليس من غير المألوف أن يفعل الكتاب ذلك عن عمد ثم يفسدون الأمر تمامًا عن طريق نسيان أن هناك الآن متغيرين يحملان نفس الاسم.يقومون بتغيير اسم المتغير الداخلي، لكنهم يتركون التعليمات البرمجية التي تستخدم المتغير، والذي يستخدم الآن دون قصد المتغير المظلل مسبقًا.وينتج عن هذا برنامج لا يزال يتم تجميعه، ولكنه ينفذ بطريقة مزعجة.

وبالمثل، ليس من غير المألوف أن يتم تظليل المتغيرات عن طريق الخطأ وتغيير سلوك البرنامج.يمكن أن يؤدي تظليل متغير موجود دون قصد إلى تغيير البرنامج بنفس سهولة إلغاء تظليل متغير كما ذكرت أعلاه.

هناك فائدة قليلة جدًا من السماح بهذا التظليل لدرجة أنهم استبعدوه باعتباره خطيرًا للغاية.على محمل الجد، فقط قم بتسمية المتغير الجديد الخاص بك بشيء آخر وستختفي المشكلة.

أعتقد أنه يؤدي إلى أخطاء يصعب اكتشافها.إنه مشابه في C#.

باسكال لا يدعم هذا، لأنه يجب عليك الإعلان عن المتغيرات فوق نص الدالة.

الافتراض الأساسي في هذا السؤال خاطئ.

جافا يفعل لديك نطاق على مستوى الكتلة.ولكنه يحتوي أيضًا على تسلسل هرمي للنطاق، ولهذا السبب يمكنك الرجوع إليه i في حدود for حلقة، ولكن لا j خارج الحلقة.

public void methodName() {
  int i = 7;
  for (int j = 0; j < 10; j++) {
    i = j * 2;
  }

  //this would cause a compilation error!
  j++;
}

لا أستطيع طوال حياتي معرفة سبب رغبتك في أن يتصرف النطاق بأي طريقة أخرى.سيكون من المستحيل تحديد أي منها i كنت تشير إلى داخل حلقة for، وأراهن أن هناك احتمالات بنسبة 99.999% من الوقت الذي تريد فيه الإشارة إلى i داخل الطريقة.

سبب آخر:إذا تم السماح بهذا النوع من إعلان المتغيرات، فسيحتاج الأشخاص (يحتاجون؟) إلى طريقة للوصول إلى متغيرات الكتلة الخارجية.قد يتم إضافة شيء مثل الكلمة الأساسية "الخارجية":

void methodName() {
    int i = 7;
    for (int j = 0; j < 10; j++) {
        int i = outer.i * 2;
        if(i > 10) {
            int i = outer.outer.i * 2 + outer.i;
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top