Variabilní stínování - Variable shadowing
v programování, variabilní stínování nastane, když je proměnná deklarována v určitém rozsah (rozhodovací blok, metoda nebo vnitřní třída) má stejný název jako proměnná deklarovaná ve vnějším oboru. Na úrovni identifikátorů (názvy, nikoli proměnné) je toto známé jako maskování jmen. O této vnější proměnné se říká, že je zastíněna vnitřní proměnnou, zatímco o vnitřním identifikátoru se říká, že maska vnější identifikátor. To může vést k nejasnostem, protože nemusí být jasné, na kterou proměnnou se následné použití názvu stínované proměnné vztahuje, což závisí na rozlišení jmen pravidla jazyka.
Jedním z prvních jazyků, které zavedly variabilní stínování, byl ALGOL, která jako první zavedla bloky pro stanovení oborů. To bylo také povoleno mnoha odvozenými programovacími jazyky včetně C, C ++ a Jáva.
The C# jazyk porušuje tuto tradici a umožňuje variabilní stínování mezi vnitřní a vnější třídou a mezi metodou a její třídou obsahující, ale ne mezi if-block a jeho obsahující metodou, nebo mezi příkazy case v přepínač blok.
Některé jazyky umožňují variabilní stínování ve více případech než jiné. Například Kotlin povolit vnitřní proměnné ve funkci stínovat předaný argument a proměnné ve vnitřním bloku stínovat jinou ve vnějším bloku, zatímco Jáva neumožňuje tyto. Oba jazyky umožňují předaný argument funkci / metodě zastínit pole třídy.[1]
Některé jazyky úplně zakazují variabilní stínování, jako je CoffeeScript.[2]
Příklad
Lua
Následující Lua kód poskytuje příklad variabilního stínování ve více blocích.
proti = 1 - globální proměnnádělat místní proti = proti + 1 - nový místní, který zastíní globální v tisk(proti) - tiskne 2 dělat místní proti = proti * 2 - další místní, který zastíní vnější místní v tisk(proti) - tiskne 4 konec tisk(proti) - tiskne 2konectisk(proti) - vytiskne 1
Krajta
Následující Krajta kód poskytuje další příklad variabilního stínování:
X = 0def vnější(): X = 1 def vnitřní(): X = 2 tisk("vnitřní:", X) vnitřní() tisk("vnější:", X)vnější()tisk("globální:", X)# výtisků# vnitřní: 2# vnější: 1# globální: 0
Protože neexistuje žádná deklarace proměnné, ale pouze přiřazení proměnné v Pythonu, klíčovém slově nelokální
zavedený v Pythonu 3 se používá k zamezení stínování proměnných a přiřazení k nelokálním proměnným:
X = 0def vnější(): X = 1 def vnitřní(): nelokální X X = 2 tisk("vnitřní:", X) vnitřní() tisk("vnější:", X)vnější()tisk("globální:", X)# výtisků# vnitřní: 2# vnější: 2# globální: 0
Klíčové slovo globální
slouží k zamezení stínování proměnných a přiřazení ke globálním proměnným:
X = 0def vnější(): X = 1 def vnitřní(): globální X X = 2 tisk("vnitřní:", X) vnitřní() tisk("vnější:", X)vnější()tisk("globální:", X)# výtisků# vnitřní: 2# vnější: 1# globální: 2
Rez
fn hlavní(){nechatX=0;{nechatX=1;tisk!(„Vnitřní x: {}“,X);// vytiskne 1}tisk!(„Vnější x: {}“,X);// vytiskne 0// StínnechatX="Rez";tisk!(„Vnější x: {}“,X);// vytiskne 'Rust'}// # Vnitřní x: 1// # Vnější x: 0// # Vnější x: Rust
C ++
#zahrnout <iostream>int hlavní(){ int X = 42; int součet = 0; pro (int i = 0; i < 10; i++) { int X = i; std::cout << "X: " << X << ''; // vytiskne hodnoty i od 0 do 9 součet += X; } std::cout << "součet:" << součet << ''; std::cout << "X: " << X << ''; // vytiskne 42 vrátit se 0;}
Jáva
veřejnost třída Stín { soukromé int myIntVar = 0; veřejnost prázdnota shadowTheVar() { // protože má stejný název jako výše uvedené pole instance objektu, stínuje výše // pole uvnitř této metody int myIntVar = 5; // Pokud jednoduše odkazujeme na 'myIntVar', bude nalezena jedna z těchto metod // (stínování druhého se stejným názvem) Systém.ven.tisk(myIntVar); // vytiskne 5 // Pokud chceme odkázat na stínovaný myIntVar z této třídy, musíme // odkaz na to takto: Systém.ven.tisk(tento.myIntVar); // vytiskne 0 } veřejnost statický prázdnota hlavní(Tětiva[] args){ Nový Stín().shadowTheVar(); }}
JavaScript
ECMAScript 6 zavedení `let` a` const` s rozsahem bloků umožňuje variabilní stínování.
funkce myFunc() { nechat my_var = 'test'; -li (skutečný) { nechat my_var = ‚nový test '; řídicí panel.log(my_var); // nový test } řídicí panel.log(my_var); // test}myFunc();