::property.isInitialized 无法区分具有相同名称的方法和属性

Zak*_*rdi 5 kotlin

我正在创建一个构建器(用于 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"
    }
Run Code Online (Sandbox Code Playgroud)

但是我遇到了一个编译问题::context.isInitialized,因为它无法区分方法context()与属性context

Kotlin 有解决方法吗?还是我被迫使用唯一的属性/方法名称?

Jit*_*a A 2

这是重载解析歧义的情况,kotlin 编译器无法识别您使用的是属性还是方法。

这是因为可调用引用 (::) 。在内部,当您使用可调用引用时,它会调用一个方法。

可调用引用:对函数、属性和构造函数的引用,除了内省程序结构之外,还可以被调用或用作函数类型的实例。

所有可调用引用的公共超类型是KCallable,其中 R 是返回值类型,对于属性来说是属性类型,对于构造函数来说是构造类型。

KCallable<out R> // supertype for all callable references
Run Code Online (Sandbox Code Playgroud)

因此,对于函数,类型是KFunction,对于属性,类型是KProperty

interface KFunction<out R> : KCallable<R>, Function<R> (source)
interface KProperty<out R> : KCallable<R> (source)
Run Code Online (Sandbox Code Playgroud)

当您使用如下函数时:

fun context(appContext: Context) = apply {
    context = appContext
}
Run Code Online (Sandbox Code Playgroud)

它可以用作函数参考

::context // This is a Function reference i.e. KFunction
Run Code Online (Sandbox Code Playgroud)

当您使用属性引用时,例如

private lateinit var context: Context
fun something(){
    ::context // this is a property reference, KProperty   
}
Run Code Online (Sandbox Code Playgroud)

可以在需要具有一个参数的函数的地方使用属性引用:

 val strs = listOf("a", "bc", "def")
 println(strs.map(String::length))
Run Code Online (Sandbox Code Playgroud)

因此,Kotlin 并不是强迫您使用不同的属性和函数名称(“尽管不推荐”)。只是在这种情况下它无法区分为

  1. 两者都是 KCallable 并且具有相同的名称
  2. 可以在需要具有一个参数的函数的地方使用属性引用