stringtranslate.com

Изменяемое затенение

В программировании затенение переменных происходит , когда переменная, объявленная в определенной области действия (блоке принятия решений, методе или внутреннем классе ), имеет то же имя, что и переменная, объявленная во внешней области действия. На уровне идентификаторов (имен, а не переменных) это известно как маскировка имен . Говорят, что эта внешняя переменная затеняется внутренней переменной, в то время как внутренний идентификатор маскирует внешний идентификатор. Это может привести к путанице, поскольку может быть неясно, к какой переменной относятся последующие использования затененного имени переменной, что зависит от правил разрешения имен языка.

Одним из первых языков, введших затенение переменных, был ALGOL , который впервые ввел блоки для установления областей видимости. Это также было разрешено многими производными языками программирования, включая C , C++ и Java .

Язык C# нарушает эту традицию, допуская затенение переменных между внутренним и внешним классом, а также между методом и содержащим его классом, но не между if-блоком и содержащим его методом или между операторами case в блоке switch .

Некоторые языки допускают затенение переменных в большем количестве случаев, чем другие. Например, Kotlin допускает внутреннюю переменную в функции затенять переданный аргумент, а переменную во внутреннем блоке — затенять другую во внешнем блоке, тогда как Java не допускает этого. Оба языка допускают, чтобы переданный аргумент функции/метода затенял поле класса. [1]

Некоторые языки полностью запрещают затенение переменных, например CoffeeScript [2] и V (Vlang) [3] .

Пример

Луа

Следующий код Lua представляет собой пример затенения переменных в нескольких блоках.

v  =  1  — глобальная переменнаяdo  local  v  =  v  +  1  — новый локальный объект, который затеняет глобальный v  print ( v )  — печатает 2 do  local  v  =  v  *  2  -- другой локальный, который затеняет внешний локальный v  print ( v )  -- печатает 4  end print ( v )  — печатает 2 конецпечать ( v )  — печатает 1

Питон

Следующий код Python представляет собой еще один пример теневого копирования переменных:

х  =  0определение  внешнего ():  x  =  1 def  inner ():  x  =  2  print ( "inner:" ,  x ) внутренняя ()  печать ( "внешняя:" ,  x )внешний () печать ( "глобальный:" ,  x )# отпечатки # внутренние: 2 # внешние: 1 # глобальные: 0

Поскольку в Python нет объявления переменных, а есть только назначение переменных, ключевое слово, nonlocalвведенное в Python 3, используется для предотвращения затенения переменных и назначения нелокальным переменным:

х  =  0определение  внешнего ():  x  =  1 def  inner ():  нелокальный  x  x  =  2  print ( "inner:" ,  x ) внутренняя ()  печать ( "внешняя:" ,  x )внешний () печать ( "глобальный:" ,  x )# отпечатки # внутренний: 2 # внешний: 2 # глобальный: 0

Ключевое слово globalиспользуется для предотвращения затенения переменных и назначения их глобальным переменным:

х  =  0определение  внешнего ():  x  =  1 def  inner ():  глобальный  x  x  =  2  print ( "inner:" ,  x ) внутренняя ()  печать ( "внешняя:" ,  x )внешний () печать ( "глобальный:" ,  x )# отпечатки # внутренние: 2 # внешние: 1 # глобальные: 2

Ржавчина

fn  main () { let x = 0 ; { // Тень let x = 1 ; println! ( "Внутренний x: {}" , x ); // печатает 1 } println! ( "Внешний x: {}" , x ); // печатает 0 let x = "Rust" ; println! ( "Внешний x: {}" , x ); // печатает 'Rust' }                            //# Внутренний x: 1 //# Внешний x: 0 //# Внешний x: Ржавчина

С++

#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' ; // выводит 42                вернуть 0 ; } 

Ява

открытый класс Shadow { частный 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 (); } }       

JavaScript

Введение ECMAScript 6let с constобластью действия блока позволяет затенять переменные.

function myFunc () { let my_var = ' test' ; if ( true ) { let my_var = ' new test' ; console.log ( my_var ) ; // новый тест } console.log ( my_var ); // тест } myFunc ( );                  

Смотрите также

Ссылки

  1. ^ "From Java to Kotlin and Back Again". Архивировано из оригинала 2020-11-28 . Получено 2021-10-04 .
  2. ^ "Пожалуйста, введите явное затенение · Проблема № 2697 · jashkenas/Coffeescript". GitHub . Архивировано из оригинала 2021-10-04 . Получено 2021-10-04 .
  3. ^ "Документация Vlang- "В отличие от большинства языков, затенение переменных не допускается"". GitHub . Получено 27.06.2024 .