为什么 Kotlin 允许在方法中声明与参数同名的变量?

问题描述 投票:0回答:4

为什么 Kotlin 允许在方法中声明与参数同名的变量?还有,有什么方法可以访问“隐藏”参数吗?

例如:

fun main(args: Array<String>) {
    val args = Any()
}
kotlin
4个回答
32
投票

这称为 shadowing,它对于将代码与系统其他部分解耦很有用。这是可能的,因为名称绑定到当前范围。

考虑一下:

你从其他人那里继承了一个类

Foo
,比如说一个API。在您的代码中引入一个变量
bar
Foo
的作者也更新了他的代码,还添加了一个变量
bar
。如果没有本地范围,就会发生冲突。

顺便说一句,这在其他 JVM 基础语言中也是可能的,包括 Java,并且常用于构造函数或 setter:

public TestClass(int value, String test) {
    this.value = value;
    this.test = test;
}

public void setFoo(String foo) {
    this.foo = foo;
}

阴影不仅仅适用于参数,其他东西也可以被阴影:字段、方法甚至类。

大多数 IDE 都会警告您有关重影的情况,因为它可能会造成混乱。

我们自己的代码推荐:

尽量避免阴影有两个原因:

  • 您的代码变得难以阅读,因为两个不同的事物具有相同的名称,这会导致混乱。
  • 一旦隐藏,您将无法再访问作用域内的原始变量。

13
投票

Kotlin 确实会发出有关名称隐藏的警告,您可以使用以下命令来抑制该警告:

@Suppress("NAME_SHADOWING")
val args = Any()

在某些情况下允许这种阴影可能会很方便,例如参数验证后抛出自定义异常:

fun sample(name: String?) {
    @Suppress("NAME_SHADOWING")
    val name = name ?: throw CustomArgumentRequiredException()
    println(name.length)
}

不幸的是,无法访问隐藏变量。

目前也不可能将 警告转变为错误


0
投票

还需要注意一些事情,如果它还没有实现或者是否有其他新人出现。在 kotlin 中,如果参数没有以 var/val 为前缀,则在将它们添加为属性之前,您无法访问它们。因此,如果一个基本类被定义为这样:

class Person(name: String, age: Int){

}

您不能使用姓名或年龄,除非它们在范围内;然而没有必要阴影 正如 miensol 指出的那样,除了期望的原因之外,但为了基本。

class Person(name: String, age: Int){
     var name = name 
     var age = age
}

在构造函数中执行这些操作

class Person(var name: String, private var age: Int){           
}

当然,您也可以根据您在创建的对象上提供的签名进行访问。


0
投票

我喜欢像

let
use
这样的安全调用块中的阴影模式,只要代码非常短并且您有嵌套块,因为在这些情况下
it
变得不明显。 在这些情况下,铁锈也会鼓励阴影,而不会像我在这篇文章中看到的那样多的珍珠抓住。

val foo: Foo? = getFoo()
foo?.use { foo -> 
  foo.doSomething()?.use { it.doSomethingElse() }
}
© www.soinside.com 2019 - 2024. All rights reserved.