Reputation: 1567
Why does Kotlin allow variable declarations with the same name as a parameter inside a method? Then also, is there any way to access the 'hidden' parameter?
For example:
fun main(args: Array<String>) {
val args = Any()
}
Upvotes: 29
Views: 36507
Reputation: 153
I like the pattern of shadowing in a safe call blocks like let
or use
as long as that code is pretty short and you have nested blocks because it
in those cases becomes non obvious. Rust encourages shadowing in those cases as well, without as much of the pearl clutching that I see in this thread.
val foo: Foo? = getFoo()
foo?.use { foo ->
foo.doSomething()?.use { it.doSomethingElse() }
}
Upvotes: 0
Reputation: 546
Something also to note and if it isn't already realized or if anyone else new comes along. In kotlin you don't have access to the params if they are not prefixed with var/val until you add them as properties. So if a basic class was defined as this:
class Person(name: String, age: Int){
}
you can't use name or age until they are in scope; however it is unnecessary to shadow with exceptions of desired reasons as miensol pointed out, but for the sake of being basic.
class Person(name: String, age: Int){
var name = name
var age = age
}
do these in the constructor
class Person(var name: String, private var age: Int){
}
you also will of course then have access based on the signature you gave on the object created.
Upvotes: 0
Reputation: 4731
This is called shadowing and it is useful for decoupling your code from other parts of the system. It is possible because names are bound to the current scope.
Consider this:
You subclass a class Foo
from someone else, let's say an API. In your code you introduce a variable bar
. The author of Foo
also updates his code and also adds a variable bar
. Without the local scope, you would get a conflict.
By the way, this is also possible in other JVM bases languages including Java and commonly used within constructors or setters:
public TestClass(int value, String test) {
this.value = value;
this.test = test;
}
public void setFoo(String foo) {
this.foo = foo;
}
Shadowing does not only apply to parameters, other things can be shadowed too: fields, methods and even classes.
Most IDEs will warn you about shadowing as it can be confusing.
Recommendation for our own code:
try to avoid shadowing for two reasons:
Upvotes: 33
Reputation: 41638
Kotlin does issue a warning about name shadowing which you can suppress with:
@Suppress("NAME_SHADOWING")
val args = Any()
Allowing for such shadowing may be handy in some cases e.g. throwing a custom exception after parameter validation:
fun sample(name: String?) {
@Suppress("NAME_SHADOWING")
val name = name ?: throw CustomArgumentRequiredException()
println(name.length)
}
It is unfortunately not possible to access the shadowed variable.
It is also not possible to turn a warning into an error at the moment.
Upvotes: 13