科特林委托性质实施“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()
}
}
}
}
的DbType
和BasicUserInfo
都保持不变。
现在,当我创建的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。
肯定有一些错误,无论是我正在运行的kotlin版本,或者可能是gradle插件(不是为android编程 - 只是使用kotlin和java插件)。当我从演示中的PropertyMapper类中移除'getValue'方法时,它仍然可以正常工作(即,只有在PropertyMapper#返回的'ReadOnlyProperty'实例的getValue方法中的TODO()但是,当我在我的项目中的机器上运行它时,尝试访问属性 –
[这里是一个示例](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) –
将我的评论移至答案 - 请参阅下面的解释。如果我可以在一个孤立的例子中一致地重现,我会提交一个错误报告 –