Kotlin中类参数与方法名冲突时,如何引用该参数?
问题
在Kotlin中,类的构造参数对类内部可见。我想把onClick定义为构造参数,但父类已经存在一个同名的onClick函数,导致我无法直接引用这个参数。
目前我能想到的办法是把参数复制到一个改名后的字段里,但总觉得不够优雅——只是把不美观的实现藏在了类内部,而这个类属于同一个项目,由同一批人维护。
原代码如下:
open class A() { // 已存在,无法修改 open fun onClick() { println("A.onClick()") } } class B(onClick: () -> Unit = { println("param onClick()") }) : A() { var x = 2 private val uglyOnClick = onClick // 临时 workaround:多了一个冗余字段 override fun onClick() { println("B.onClick() $x") if (x-- > 0) { // 防止递归无限循环(理想情况下不会发生) super.onClick() // this@B.onClick() // 递归,不是想要的参数引用 // this.onClick() // 递归,不是想要的参数引用 // onClick() // 递归,不是想要的参数引用 /* 以上三种写法的输出: B.onClick() 2 A.onClick() B.onClick() 1 A.onClick() B.onClick() 0 */ // getOnClick() // 无法解析引用 uglyOnClick() // 这个能正常工作,但写法太丑 /* 这个写法的预期输出: B.onClick() 2 A.onClick() param onClick() */ } } }
期望实现的效果:
class B(onClick: () -> Unit = { println("param onClick()") }) : A() { override fun onClick() { println("B.onClick()") super.onClick() :::MAGIC:::.onClick() // 这里能直接引用构造参数onClick } } } /* 预期输出: B.onClick() A.onClick() param onClick() */
解决方案
不需要额外改名,直接把构造参数声明为类的私有属性,通过属性调用的方式区分同名方法即可:
open class A() { open fun onClick() { println("A.onClick()") } } class B(private val onClick: () -> Unit = { println("param onClick()") }) : A() { override fun onClick() { println("B.onClick()") super.onClick() // 通过属性引用调用构造参数的lambda this.onClick.invoke() // 或者更简洁的写法: // (this.onClick)() } }
原理说明
- 把构造参数
onClick声明为private val onClick后,它会成为类的私有属性,和同名的onClick()方法共存。 - 在类内部,直接写
onClick()会优先调用成员方法;但通过this.onClick可以获取到属性的lambda实例,再通过invoke()或者加括号调用,就能执行构造参数传入的逻辑。
这种写法避免了冗余的改名字段,实现更简洁优雅,同时保持代码可读性。
内容的提问来源于stack exchange,提问作者18446744073709551615
相关产品推荐
相关产品推荐

