Sombreamento variável
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. [1]
Algumas linguagens não permitem completamente o sombreamento de variáveis, como CoffeeScript . [2]
Exemplo
[editar | editar código-fonte]Lua
[editar | editar código-fonte]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
[editar | editar código-fonte]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
[editar | editar código-fonte]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++
[editar | editar código-fonte]#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
[editar | editar código-fonte]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
[editar | editar código-fonte]
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();
Veja também
[editar | editar código-fonte]Referências
[editar | editar código-fonte]- ↑ «From Java to Kotlin and Back Again». Consultado em 4 de outubro de 2021. Arquivado do original em 28 de novembro de 2020
- ↑ «Please introduce explicit shadowing · Issue #2697 · jashkenas/Coffeescript». GitHub. Consultado em 4 de outubro de 2021. Arquivado do original em 4 de outubro de 2021