我想使用具有一些注释的所有属性的值.在大多数情况下,我的代码都有效,我得到了所有的属性,只接受了那些有注释的属性.
private inline fun <reified A : Annotation> (target: Any) {
target::class.memberProperties
.filter { it.annotations.any { annotation -> annotation is A } }
.forEach {
// How do I get the value here?
}
}
Run Code Online (Sandbox Code Playgroud)
我想使用it.get(...)
但是get
期望一个Nothing
as参数.同样如此getter
.调用it.call(target)
确实有效但看起来不对,因为有一个get
我不知道如何调用的实际值.
那么获取属性值的正确方法是什么?
问题归结为T::class
给你一个KClass<T>
,而t::class
给你一个KClass<out T>
.考虑以下:
class Foo {
val foo = 2
val bar = 3
}
fun f() {
val any: Any = Foo()
any::class.memberProperties.forEach {
println(it.get(2)) // Oops
}
}
Run Code Online (Sandbox Code Playgroud)
这将从根本上试图访问2.foo
和2.bar
,但它不允许的,因为get
谨慎的一侧允许犯错类型的参数,而不是Any
.然而,它似乎t.javaClass.kotlin
会产生一个KClass<T>
.如上所述滥用它会导致IllegalArgumentException
.
您可以通过提供编译时保证KClass
将为编译器提供更多帮助,该保证将是类型而不是其他内容:
private inline fun <reified A : Annotation, reified T : Any> foo(target: T) {
T::class.memberProperties
.filter { it.annotations.any { annotation -> annotation is A } }
.forEach {
println(it.get(target))
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,我不知道这是否是可能的指定A
而推导T
从target
.我还没有找到一种方式来称呼它foo<Attr, Bar>(bar)
.
或者,您可以通过javaClass
,虽然我打赌它不太便携:
private inline fun <reified A : Annotation> foo(target: Any) {
target.javaClass.kotlin.memberProperties
.filter { it.annotations.any { annotation -> annotation is A } }
.forEach {
println(it.get(target))
}
}
Run Code Online (Sandbox Code Playgroud)
我们知道这不会遇到上述问题,因为我们在两种情况下都传递相同的对象.这在呼叫者方面也看起来更好,假设有一个,可能值得携带.
归档时间: |
|
查看次数: |
1928 次 |
最近记录: |