为什么 Kotlin 允许在方法中声明与参数同名的变量?还有,有什么方法可以访问“隐藏”参数吗?
例如:
fun main(args: Array<String>) {
val args = Any()
}
这称为 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 都会警告您有关重影的情况,因为它可能会造成混乱。
我们自己的代码推荐:
尽量避免阴影有两个原因:
Kotlin 确实会发出有关名称隐藏的警告,您可以使用以下命令来抑制该警告:
@Suppress("NAME_SHADOWING")
val args = Any()
在某些情况下允许这种阴影可能会很方便,例如参数验证后抛出自定义异常:
fun sample(name: String?) {
@Suppress("NAME_SHADOWING")
val name = name ?: throw CustomArgumentRequiredException()
println(name.length)
}
不幸的是,无法访问隐藏变量。
目前也不可能将 警告转变为错误。
还需要注意一些事情,如果它还没有实现或者是否有其他新人出现。在 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){
}
当然,您也可以根据您在创建的对象上提供的签名进行访问。
我喜欢像
let
或 use
这样的安全调用块中的阴影模式,只要代码非常短并且您有嵌套块,因为在这些情况下 it
变得不明显。 在这些情况下,铁锈也会鼓励阴影,而不会像我在这篇文章中看到的那样多的珍珠抓住。
val foo: Foo? = getFoo()
foo?.use { foo ->
foo.doSomething()?.use { it.doSomethingElse() }
}