我正在创建一个构建器(用于Java兼容),其中context
既是私有属性又是公共方法。
private lateinit var context: Context
fun context(appContext: Context) = apply {
context = appContext
}
fun build(): MySdk {
// this::context fails to compile because it cannot differentiate between the
// method `context()` vs property `context`
require(this::context.isInitialized) {
"context == null"
}
但是我遇到了::context.isInitialized
的编译问题,因为它无法区分方法context()
与属性context
科特林是否有解决方法?还是我被迫使用唯一的属性/方法名称?
答案 0 :(得分:2)
这是重载解决方案模棱两可的情况,并且kotlin编译器无法识别您是使用属性还是方法。
这是因为有可调用的引用(::)。在内部,当您使用可调用引用时,它会调用一个方法。
Callable references:对函数,属性和 构造函数除了自省程序结构外,还可以 被称为或用作功能类型的实例。
所有可调用引用的公共超类型是KCallable,其中R是返回值类型,它是属性的属性类型,而构造函数是构造函数。
KCallable<out R> // supertype for all callable references
因此,对于函数,类型为KFunction,对于属性,类型为KProperty
interface KFunction<out R> : KCallable<R>, Function<R> (source)
interface KProperty<out R> : KCallable<R> (source)
当您使用类似:的功能时
fun context(appContext: Context) = apply {
context = appContext
}
可用作功能参考
::context // This is a Function reference i.e. KFunction
使用属性引用时,例如
private lateinit var context: Context
fun something(){
::context // this is a property reference, KProperty
}
可以在需要带有一个参数的函数的地方使用属性引用:
val strs = listOf("a", "bc", "def")
println(strs.map(String::length))
因此,并不是Kotlin会强迫您使用不同的属性和函数名称(“尽管不建议”)。只是在这种情况下无法区分
答案 1 :(得分:1)
您可以通过提供期望的类型来解决属性和方法之间的歧义:
val prop: kotlin.reflect.KProperty0<*> = this::context
A,prop.isInitialized
然后给出了编译错误:
This declaration can only be called on a property literal (e.g. 'Foo::bar')
因此,目前看来这不可能。 OTOH,由于错误表明isInitialized
已由编译器专门处理,因此很可能可以修复;我建议在http://youtrack.jetbrains.com/上进行报告(在搜索重复项之后)。