科特林委托性质实施“provideDelegate”操作的功能,但方法从来没有所谓

问题描述:

我有一个基本类型DbType这是开放的延长我的模型是这样的:科特林委托性质实施“provideDelegate”操作的功能,但方法从来没有所谓

interface DbType { 
    fun <T : Any> field() = PropertyMapper<T>() 
} 

PropertyMapper类是这样实现的:

class PropertyMapper<out T : Any> internal constructor() { 

    @Suppress("UNCHECKED_CAST") operator fun getValue(inst: DbType, prop: KProperty<*>): T { 
     return ImplementationDetail.values?.get(prop.name) as T? ?: throw NullPointerException("No such ${prop.name} in type ${inst::class}") 
    } 

    operator fun provideDelegate(inst: DbType, prop: KProperty<*>): ReadOnlyProperty<DbType, T> { 
     TODO() 
    } 
} 

按照科特林文档中this项,我应该能够自己ReadOnlyProperty<R, T>通过在类中添加操作功能provideDelegate以提供该财产被委托给。但是,当我实例化一个实现/扩展DbType的对象时,操作员函数provideDelegate从不被调用。 “getValue”部分工作正常,但我想拦截创建对象时的属性委托创建。任何想法我做错了吗?下面是一个示例类:

class BasicUserInfo : DbType { 
    val username by field<String>() 
} 

我想通了:它似乎是kotlin插件或gradle中的一个bug。如果我使用PropertyMapper构建一个干净的项目,只有一个名为getValue的单一运算符方法,它将按预期工作:在访问该字段时调用PropertyMapper#getValue

然后,当我删除该方法并改为使用provideDelegate运算符方法时,它将失败,并显示NoSuchMethodError(从不调用PropertyMapper#provideDelegate方法)。如果我清理(手动删除构建/出文件夹)并用该设置重新构建,它运行得很好。

确定它没有被调用?我在代码中发现错误的是,当您实现provideDelegate运算符并且返回接收方以外的某个代理对象时,您不需要实现getValue运算符,因为它不会被使用,它是provideDelegate返回将用于属性访问(请参见下文)。

否则,您的代码是有效的。我稍微修改你的榜样,使之更加清楚发生了什么:

class PropertyMapper<out T : Any> internal constructor() { 
    operator fun getValue(inst: DbType, prop: KProperty<*>): T { 
     println("PropertyMapper :: getValue") // note: never printed 
     TODO() 
    } 

    operator fun provideDelegate(inst: DbType, prop: KProperty<*>): ReadOnlyProperty<DbType, T> { 
     println("PropertyMapper :: provideDelegate") 
     return object : ReadOnlyProperty<DbType, T> { 
      override fun getValue(thisRef: DbType, property: KProperty<*>): T { 
       println("anonymous ReadOnlyProperty :: getValue") 
       TODO() 
      } 
     } 
    } 
} 

DbTypeBasicUserInfo都保持不变。

现在,当我创建的BasicUserInfo一个实例,并得到其username(与表达BasicUserInfo().username),我得到下面的输出:

PropertyMapper :: provideDelegate 
anonymous ReadOnlyProperty :: getValue 
Exception in thread "main" kotlin.NotImplementedError: An operation is not implemented. 
... 

如果我只创建实例,它是只有第一行。请参阅the runnable demo of this code

+0

肯定有一些错误,无论是我正在运行的kotlin版本,或者可能是gradle插件(不是为android编程 - 只是使用kotlin和java插件)。当我从演示中的PropertyMapper类中移除'getValue'方法时,它仍然可以正常工作(即,只有在PropertyMapper#返回的'ReadOnlyProperty'实例的getValue方法中的TODO()但是,当我在我的项目中的机器上运行它时,尝试访问属性 –

+0

[这里是一个示例](https://try.kotlinlang。)时,会失败,并显示'NoSuchMethodError'。org /#/ UserProjects/i80l089pasrufarmko4a1juhju/smrs60ai2hva4c7hpffjbrvalq)(我修改了你的),这更接近我想要做的和[这里是存储库](https://github.com/prestongarno/ktq-codegen),更具体地说:[interface](https://github.com/prestongarno/ktq-codegen/blob/master/runtime/src/main/java/com/prestongarno/ktq/runtime/GraphType.kt)和[implementation](https ://github.com/prestongarno/ktq-codegen/blob/master/compiler/src/test/java/com/prestongarno/transpiler/experimental/Query.kt) –

+0

将我的评论移至答案 - 请参阅下面的解释。如果我可以在一个孤立的例子中一致地重现,我会提交一个错误报告 –