Na programação de computadores, o sombreamento de variáveis ocorre quando uma variável declarada em um determinado escopo tem o mesmo nome de uma variável declarada em um escopo externo (nível superior ao atual). No nível dos identificadores, isso é conhecido como mascaramento de nomes. Quando isso ocorre, diz-se que esta variável externa é sombreada pela variável interna, enquanto o identificador interno mascara o identificador externo. Isso pode causar confusão na leitura, por poder não estar claro a qual variável os usos subsequentes do nome da variável sombreada se referem, o que depende das regras de resolução de nomes da linguagem.

O sombreamento de variáveis foi introduzido inicialmente em ALGOL, uma das primeiras linguagens a empregar blocos para definir escopos. Esse conceito foi adotado por muitas outras linguagens de programação que se originaram dela, como C, C++ e Java.

A linguagem C# desvia dessa tradição ao permitir o sombreamento de variáveis entre uma classe interna e uma classe externa, e também entre um método e a classe que o contém. No entanto, não permite o sombreamento entre um bloco if e o método que o contém, nem entre instruções case em um bloco switch.

Há variações na permissão de sombreamento de variáveis entre as linguagens. Por exemplo, Kotlin permite que uma variável interna em uma função oculte um argumento passado e uma variável em um bloco interno oculte a variável do bloco externo, enquanto Java não permite essa flexibilidade. No entanto, ambas as linguagens permitem que um argumento passado para uma função ou método oculte um campo de classe.

Algumas linguagens não permitem completamente o sombreamento de variáveis, como CoffeeScript .

Exemplo

Lua O código Lua a seguir fornece um exemplo de sombreamento de variável, onde v é declarado em múltiplas instâncias.v = 1 -- declara v como variavel global

do local v = v + 1 -- declara um novo v local que sombreia a variavel global -- mas v'segundo' = v'global' + 1 print(v) -- imprime 2

do local v = v * 2 -- novamente é declarado uma nova variavel com mesmo nome -- v'terceiro' = v'segundo' * 2 print(v) -- imprime 4 end

print(v) -- imprime 2 end

print(v) -- imprime 1

Python A seguir um exemplo de sombreamento de variável em Python:# Atribui um valor à variável no escopo global x = 0

def outer(): # Atribui um valor à variável no escopo da função outer x = 1

def inner(): # Atribui um valor à variável no escopo da função inner x = 2 # Imprime x no escopo da função inner: saída "inner: 2" print("inner:", x)

inner() # imprime x no escopo da função outer: saída "outer: 1" print("outer:", x)

outer() # imprime x no escopo global: saída "global: 0" print("global:", x)Em Python, onde não há uma declaração explícita de variável, mas sim apenas atribuição, a palavra-chave nonlocal, introduzida em Python3, é utilizada para evitar a ocorrência de sombreamento de variáveis e permitir a atribuição a variáveis em escopos externos ao local atual de execução. # Atribui um valor à variável no escopo global x = 0

def outer(): # Atribui um valor à variável no escopo da função outer x = 1

def inner(): # Acessa a variável x no escopo de outer, escopo anterior nonlocal x # Atribui um novo valor à variável x no escopo de outer x = 2 # Imprime x no escopo da função inner saída: "inner: 2" print("inner:", x)

inner() # Imprime x no escopo da função outer saída: "outer: 2" print("outer:", x)

outer() # Imprime x no escopo global saída: "global: 0" print("global:", x)A palavra-chave global é usada para evitar o sombreamento de variáveis e acessa a atribuição globais:# Atribui um valor à variável no escopo global x = 0

def outer(): # Atribui um valor à variável no escopo da função outer x = 1

def inner(): # Permite acessar e atribuir a variável global x global x # Atribui um novo valor à variável global x x = 2 # Imprime x no escopo da função inner saída: "inner: 2" print("inner:", x)

inner() # Imprime x no escopo da função outer saída: "outer: 1" print("outer:", x)

outer() # Imprime x no escopo global saída: "global: 1" print("global:", x)

Rust fn main() { let x = 0; // Atribui um valor à variável no escopo principal

// Sombreamento let x = 1; // Atribui um novo valor à variável no escopo interno println!("Inner x: {}", x); // Imprime x no escopo interno saída: "Inner x: 1"

println!("Outer x: {}", x); // Imprime x no escopo externo saída: "Outer x: 0"

let x = "Rust"; // Atribui um novo valor à variável no escopo principal println!("Outer x: {}", x); // Imprime x no escopo externos saída: "Outer x: Rust" }

C++ #include <iostream>

int main() { int x = 42; // Atribui um valor à variável x no escopo principal int sum = 0; // Atribui um valor à variável sum no escopo principal

for (int i = 0; i < 10; i++) { int x = i; // Atribui um novo valor à variável x no escopo do loop std::cout << "x: " << x << '\n'; // Imprime os valores de x de 0 a 9 sum += x; // Atualiza a variável sum com o valor de x

std::cout << "sum: " << sum << '\n';// Imprime a soma dos valores de x : 45 std::cout << "x: " << x << '\n'; // Imprime o valor de x no escopo principal: 42

return 0; }

Java public class Shadow { private int myIntVar = 0; // Atribui um valor a variavel myIntVar

public void shadowTheVar() { // Como tem o mesmo nome que o campo de instância acima, ele sombreia // o campo acima dentro deste método. int myIntVar = 5; // Atribui um novo valor à variável local myIntVar

// Se simplesmente nos referirmos a 'myIntVar', o valor desta variável local // é encontrado (sombreando uma segunda variável com o mesmo nome) System.out.println(myIntVar); // Imprime myIntVar no escopo deste método: 5

// Se quisermos nos referir ao myIntVar sombreado desta classe, precisamos // nos referir a ele assim: System.out.println(this.myIntVar); // Imprime myIntVar sombreado: 0

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

JavaScript No ECMAScript 6 de JavaScript as instruções let e const com escopo de bloco permitem o sombreamento de variável.function myFunc() { let my_var = 'test'; // Atribui um valor à variável no escopo da função if (true) { let my_var = 'new test'; // Atribui um novo valor à variável no escopo do bloco if console.log(my_var); // Imprime my_var no escopo do bloco if: 'new test'

console.log(my_var); // Imprime my_var no escopo da função: 'test' } myFunc();

Ver também

Sobrecarga Polimorfismo de tipo Vinculação de nome

Referências

Categoria:Variável (programação)