Переменное затенение
В компьютерном программировании затенение переменных происходит, когда переменная, объявленная в определенной области (блоке принятия решений, методе или внутреннем классе ), имеет то же имя, что и переменная, объявленная во внешней области. На уровне идентификаторов (имен, а не переменных) это называется маскированием имени . Говорят, что эта внешняя переменная затенена внутренней переменной, тогда как внутренний идентификатор маскирует внешний идентификатор. Это может привести к путанице, поскольку может быть неясно, к какой переменной относятся последующие использования имени затененной переменной, что зависит от правил разрешения имен языка.
Одним из первых языков, в котором было реализовано затенение переменных, был ALGOL , в котором впервые были введены блоки для установления областей видимости. Это также было разрешено многими производными языками программирования, включая C , C++ и Java .
Язык C# нарушает эту традицию, допуская затенение переменных между внутренним и внешним классом, а также между методом и содержащим его классом, но не между блоком if и содержащим его методом или между операторами case в блоке переключателя .
Некоторые языки допускают затенение переменных в большем количестве случаев, чем другие. Например , Kotlin позволяет внутренней переменной в функции скрывать переданный аргумент, а переменная во внутреннем блоке — скрывать другую во внешнем блоке, тогда как Java этого не позволяет. Оба языка позволяют передавать аргумент функции/методу для скрытия поля класса. [1]
Некоторые языки полностью запрещают затенение переменных, например CoffeeScript . [2]
Пример [ править ]
Возьмите [ править ]
Следующий код 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
end
print ( v ) — печатает 1
Питон [ править ]
Следующий код Python представляет собой еще один пример затенения переменных:
x = 0
def Outer ():
x = 1
Def Inner ():
x = 2
print ( «inner:» , x )
внутренний ()
print ( «outer:» , x )
внешний ()
print ( «global:» , x )
# печатает
# внутреннее: 2
# внешнее: 1
# глобальное: 0
Поскольку в Python нет объявления переменных, а есть только присвоение переменных, ключевое слово nonlocal
представленный в Python 3, используется, чтобы избежать затенения переменных и присвоения нелокальных переменных:
x = 0
def external ():
x = 1
def Internal ():
нелокальный x
x = 2
print ( «inner:» , x )
внутренний ()
print ( «outer:» , x )
внешний ()
print ( «global: " , x )
# печатает
# внутренний: 2
# внешний: 2
# глобальный: 0
Ключевое слово global
используется, чтобы избежать затенения переменных и присваивания глобальным переменным:
x = 0
def external ():
x = 1
def Internal ():
global x
x = 2
print ( «inner:» , x )
внутренний ()
print ( «outer:» , x )
внешний ()
print ( «global: " , x )
# печатает
# внутренний: 2
# внешний: 1
# глобальный: 2
Ржавчина [ править ]
fn main () {
let x = 0 ;
{
// Тень
let x = 1 ;
распечататьлн! ( "Внутренний x: {}" , x ); // печатает 1
}
println! ( "Внешний x: {}" , x ); // печатает 0
let x = "Rust" ;
распечататьлн! ( "Внешний x: {}" , x ); // печатает 'Rust'
}
//# Внутренний x: 1
//# Внешний x: 0
//# Внешний x: Rust
С++ [ править ]
#include <iostream>
int main ()
{
int x = 42 ;
интервал сумма = 0 ;
для ( int я знак равно 0 ; я < 10 ; я ++ ) {
int x знак равно я ;
std :: cout << "x:" << x << '\n' ; // печатает значения i от 0 до 9
sum += x ;
}
std :: cout << "sum:" << sum << '\n' ;
std :: cout << "x:" << x << '\n' ; // выводит 42
return 0 ;
}
Ява [ править ]
общественный класс Shadow {
частное int myIntVar = 0 ;
public voidshadowTheVar // Поскольку оно имеет то же имя , () {
что и поле экземпляра объекта выше, оно затеняет
// поле выше внутри этого метода.
int myIntVar = 5 ;
// Если мы просто ссылаемся на 'myIntVar', то будет найден один из этих методов
// (затеняющий второй с тем же именем)
System . вне . println ( myIntVar ); // печатает 5
// Если мы хотим обратиться к затененному myIntVar из этого класса, нам нужно
// обратиться к нему так:
System . вне . println ( это .myIntVar ) ; // печатает 0
}
public static void main ( String [] args ) {
new Shadow (). теньТеВар ();
}
}
JavaScript [ править ]
ECMAScript 6: введение let
и const
с областью действия блока позволяют затенение переменных.
function myFunc () {
let my_var = 'test' ;
if ( true ) {
let my_var = 'новый тест' ;
консоль . журнал ( my_var ); // новый тест
}
console . журнал ( my_var ); // проверка
}
myFunc ();
См. также [ править ]
Ссылки [ править ]
- ^ «От Java к Котлину и обратно» . Архивировано из оригинала 28 ноября 2020 г. Проверено 4 октября 2021 г.
- ^ «Пожалуйста, введите явное затенение · Проблема № 2697 · jashkenas/Coffeescript» . Гитхаб . Архивировано из оригинала 04 октября 2021 г. Проверено 4 октября 2021 г.