Переменное затенение - Variable shadowing

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

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

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

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

Некоторые языки полностью запрещают затенение переменных, например CoffeeScript .

Пример

Lua

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

v = 1 -- a global variable

do
  local v = v + 1 -- a new local that shadows global v
  print(v) -- prints 2

  do
    local v = v * 2 -- another local that shadows outer local v
    print(v) -- prints 4
  end

  print(v) -- prints 2
end

print(v) -- prints 1

Python

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

x = 0

def outer():
    x = 1

    def inner():
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# prints
# inner: 2
# outer: 1
# global: 0

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

x = 0

def outer():
    x = 1

    def inner():
        nonlocal x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# prints
# inner: 2
# outer: 2
# global: 0

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

x = 0

def outer():
    x = 1

    def inner():
        global x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# prints
# inner: 2
# outer: 1
# global: 2

Ржавчина

fn main() {
    let x = 0;
    
    {
        let x = 1;
        println!("Inner x: {}", x); // prints 1
    }
    
    println!("Outer x: {}", x); // prints 0
    
    // Shadow
    let x = "Rust";
    println!("Outer x: {}", x);  // prints 'Rust'
}

//# Inner x: 1
//# Outer x: 0
//# Outer x: Rust

C ++

#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'; // prints values of i from 0 to 9
    sum += x;
  }

  std::cout << "sum: " << sum << '\n';
  std::cout << "x:   " << x   << '\n'; // prints out 42

  return 0;
}

Джава

public class Shadow {
    private int myIntVar = 0;

    public void shadowTheVar() {
        // Since it has the same name as above object instance field, it shadows above 
        // field inside this method.
        int myIntVar = 5;

        // If we simply refer to 'myIntVar' the one of this method is found 
        // (shadowing a second one with the same name)
        System.out.println(myIntVar); // prints 5

        // If we want to refer to the shadowed myIntVar from this class we need to 
        // refer to it like this:
        System.out.println(this.myIntVar); // prints 0
    }

    public static void main(String[] args){
        new Shadow().shadowTheVar();
    }
}

JavaScript

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

function myFunc() {
    let my_var = 'test';
    if (true) {
        let my_var = 'new test';
        console.log(my_var); // new test
    }
    console.log(my_var); // test
}
myFunc();

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

использованная литература

  1. ^ "Архивная копия" . Архивировано 28 ноября 2020 года . Проверено 2021-10-04 .CS1 maint: заархивированная копия как заголовок ( ссылка )
  2. ^ "Архивная копия" . Архивировано 4 октября 2021 года . Проверено 2021-10-04 .CS1 maint: заархивированная копия как заголовок ( ссылка )