Skip to content

Commit 41659d0

Browse files
authored
Merge pull request #875 from hangga/variable-shadowing
KTLN-457 : Variable Shadowing in Kotlin
2 parents 4ce37bf + f01e877 commit 41659d0

File tree

1 file changed

+207
-0
lines changed

1 file changed

+207
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
@file:Suppress("UNUSED_VARIABLE", "UNUSED_ANONYMOUS_PARAMETER")
2+
3+
package com.baeldung.variableshadowing
4+
5+
import org.junit.jupiter.api.Assertions.assertEquals
6+
import org.junit.jupiter.api.Test
7+
8+
class VariableShadowingUnitTest {
9+
10+
@Test
11+
fun `top-level variable shadowing`() {
12+
val number = 10 // Top-level variable
13+
14+
fun upNumber(): Int { // top-level function
15+
val number = 20 // shadowing top-level variable
16+
return number
17+
}
18+
19+
assertEquals(20, upNumber())
20+
assertEquals(10, number)
21+
}
22+
23+
@Test
24+
fun `solution to avoid top-level variable shadowing`() {
25+
val topLevelNumber = 10 // Top-level variable
26+
27+
fun upNumber(): Int {
28+
val localNumber = 20 // Local variable without shadowing
29+
return localNumber
30+
}
31+
32+
assertEquals(20, upNumber())
33+
assertEquals(10, topLevelNumber)
34+
}
35+
36+
@Test
37+
fun `shadowing class member`() {
38+
class Car {
39+
val speed: Int = 100
40+
41+
fun upSpeed(): Int {
42+
val speed = speed * 2 // Shadowing class member named 'speed'
43+
return speed
44+
}
45+
}
46+
47+
assertEquals(100, Car().speed)
48+
assertEquals(200, Car().upSpeed())
49+
}
50+
51+
@Test
52+
fun `solution to avoid shadowing class member`() {
53+
class Car {
54+
val speed: Int = 100
55+
56+
fun newSpeed(): Int {
57+
val newSpeed = speed * 2 // Using a new variable name to avoid shadowing
58+
return newSpeed
59+
}
60+
61+
fun upSpeed(): Int {
62+
return this.speed * 2 // Use the outer speed directly with this keyword
63+
}
64+
}
65+
66+
assertEquals(100, Car().speed)
67+
assertEquals(200, Car().upSpeed())
68+
assertEquals(200, Car().newSpeed())
69+
}
70+
71+
@Test
72+
fun `local variable shadowing`() {
73+
fun calculateTotalPrice(discount: Int) {
74+
val discount = discount + 10 // Shadowing the parameter 'discount'
75+
assertEquals(30, discount)
76+
77+
val price = 100 // local variable
78+
val discountRate = 0.1
79+
80+
fun applyDiscount(price: Int): Double { // Nested function with parameter named 'price'
81+
val discountRate = 0.2 // shadowing the outer variable discountRate
82+
return price * (1 - discountRate) // 'price' here refers to the parameter, not the outer variable
83+
}
84+
85+
assertEquals(80.0, applyDiscount(price))
86+
}
87+
88+
calculateTotalPrice(20)
89+
}
90+
91+
@Test
92+
fun `solution to avoid local variable shadowing`() {
93+
fun calculateTotalPrice(discount: Int) {
94+
val updatedDiscount = discount + 10 // Using a new variable name to avoid shadowing
95+
assertEquals(30, updatedDiscount)
96+
97+
val price = 100 // local variable
98+
val discountRate = 0.1
99+
100+
fun applyDiscount(price: Int): Double {
101+
return price * (1 - discountRate) // Use the outer discountRate directly
102+
}
103+
104+
assertEquals(90.0, applyDiscount(price))
105+
}
106+
107+
calculateTotalPrice(20)
108+
}
109+
110+
111+
@Test
112+
fun `shadowing in loop`() {
113+
val numbers = listOf(1, 2, 3, 4, 5)
114+
115+
// shadowing in loop
116+
for (number in numbers) {
117+
val number = number * 2 // Shadowing the loop variable 'number'
118+
}
119+
}
120+
121+
@Test
122+
fun `solution to avoiding shadowing in loop`() {
123+
val numbers = listOf(1, 2, 3, 4, 5)
124+
125+
// avoiding shadowing in loop
126+
for (number in numbers) {
127+
val newNumber = number * 2 // Using a new variable name to avoid shadowing
128+
}
129+
}
130+
131+
132+
@Test
133+
fun `shadowing in extension`() {
134+
val numbers = listOf(1, 2, 3, 4, 5)
135+
136+
assertEquals(15, numbers.sum())
137+
138+
fun List<Int>.sum(): Int { // shadowing built-in function sum()
139+
var sum = 0
140+
this.forEach { sum += it * 2 }
141+
return sum
142+
}
143+
144+
assertEquals(30, numbers.sum())
145+
}
146+
147+
@Test
148+
fun `solution to avoiding shadowing in extension`() {
149+
val numbers = listOf(1, 2, 3, 4, 5)
150+
151+
// in extension
152+
assertEquals(15, numbers.sum())
153+
154+
fun List<Int>.sumByTwo(): Int { // using another name to avoid shadowing
155+
var sum = 0
156+
this.forEach { sum += it * 2 }
157+
return sum
158+
}
159+
160+
assertEquals(30, numbers.sumByTwo())
161+
162+
val doubledSum = numbers.sumOf { it * 2 } // Modify lambda in sum
163+
assertEquals(30, doubledSum)
164+
}
165+
166+
167+
@Test
168+
fun `shadowing in lambda`() {
169+
val numbers = listOf(1, 2, 3, 4, 5)
170+
171+
var sum = 0
172+
173+
numbers.forEach { number ->
174+
val number = 0 // shadowing value
175+
sum += number
176+
}
177+
178+
assertEquals(0, sum)
179+
180+
val lambda = { number: Int ->
181+
val number = 1 // Local variable in lambda
182+
}
183+
}
184+
185+
@Test
186+
fun `solution to avoiding shadowing in lambda`() {
187+
val numbers = listOf(1, 2, 3, 4, 5)
188+
189+
// in lambda
190+
var sum = 0
191+
192+
numbers.forEach { number ->
193+
val newNumber = 0 // Using a new variable name to avoid shadowing
194+
sum += newNumber
195+
}
196+
197+
assertEquals(0, sum)
198+
199+
numbers.forEach { number ->
200+
sum += number // Directly access the current element in the loop
201+
}
202+
203+
assertEquals(15, sum) // Assuming we want the sum of the original numbers
204+
205+
}
206+
207+
}

0 commit comments

Comments
 (0)