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