如何通过反射收集成员以稍后作为参数传递
How to collect members via reflection to pass as argument later
所以,我正在研究一个概念,涉及自动写入 ByteBuffer
扩展 Bufferizable
的 class 的内容
abstract class Bufferizable {
abstract val fieldOrder: Array<String>
open fun size(): Int = TODO()
var initialized = false
open infix fun to(address: Long) {
if (initialized) {
addFunctions.forEach { }
} else {
addFunctions = Array(fieldOrder.size) { null }
members = Array(fieldOrder.size) { null }
fieldOrder.forEachIndexed { i, field ->
val member = this::class.declaredMemberProperties.find { it.name == field }!!
addFunctions[i] = when (member.returnType) {
Mat4::class.defaultType.javaType -> WithAddress::addMat4
...
else -> throw Error()
} as BufferizableAddFunctionType
members[i] = member.get(this) // error
}
initialized = true
}
}
infix fun from(address: Long): Unit = TODO()
var addFunctions = arrayOf<BufferizableAddFunctionType?>()
var members = arrayOf<Any?>()
}
typealias BufferizableAddFunctionType = (Any) -> Unit
object WithAddress {
var address = NULL
var offset = 0
fun addMat4(mat4: Mat4) {
for (i in 0..3)
for (j in 0..3) {
memPutFloat(address + offset, mat4[i, j])
offset += Float.BYTES
}
}
...
}
思路就是声明,比如下面这样
object uboVS : Bufferizable() {
var projectionMatrix = Mat4()
var modelMatrix = Mat4()
...
override val fieldOrder = arrayOf("projectionMatrix", "modelMatrix", "viewMatrix")
}
然后每当 uboVS to address
第一次被调用时,它会被初始化,然后按照指定的顺序将其内容写入本机地址。
但我遇到的唯一问题是收集成员以作为参数传递给第 i 个 addFunction
因为编译器在这里报错:
members[i] = member.get(this)
Error:(328, 37) Kotlin: Out-projected type 'KProperty1' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1'
我该如何解决?
这是一个继承问题。您的反射调用 this::class.declaredMemberProperties.find{ ... }
returns a KProperty1<out Bufferizable, Any?>
这意味着 属性 来自继承自 Bufferizable 的东西(有关 out
的更多信息,请参阅 declaration-site variance) .通过编译器不知道这个 属性 属于哪个 class 它不允许直接访问。要解决此问题,您必须访问 getter 函数:
members[i] = member.getter.call(this)
通过getter函数属于对象不属于反射api遵循默认的继承行为,可以调用
所以,我正在研究一个概念,涉及自动写入 ByteBuffer
扩展 Bufferizable
abstract class Bufferizable {
abstract val fieldOrder: Array<String>
open fun size(): Int = TODO()
var initialized = false
open infix fun to(address: Long) {
if (initialized) {
addFunctions.forEach { }
} else {
addFunctions = Array(fieldOrder.size) { null }
members = Array(fieldOrder.size) { null }
fieldOrder.forEachIndexed { i, field ->
val member = this::class.declaredMemberProperties.find { it.name == field }!!
addFunctions[i] = when (member.returnType) {
Mat4::class.defaultType.javaType -> WithAddress::addMat4
...
else -> throw Error()
} as BufferizableAddFunctionType
members[i] = member.get(this) // error
}
initialized = true
}
}
infix fun from(address: Long): Unit = TODO()
var addFunctions = arrayOf<BufferizableAddFunctionType?>()
var members = arrayOf<Any?>()
}
typealias BufferizableAddFunctionType = (Any) -> Unit
object WithAddress {
var address = NULL
var offset = 0
fun addMat4(mat4: Mat4) {
for (i in 0..3)
for (j in 0..3) {
memPutFloat(address + offset, mat4[i, j])
offset += Float.BYTES
}
}
...
}
思路就是声明,比如下面这样
object uboVS : Bufferizable() {
var projectionMatrix = Mat4()
var modelMatrix = Mat4()
...
override val fieldOrder = arrayOf("projectionMatrix", "modelMatrix", "viewMatrix")
}
然后每当 uboVS to address
第一次被调用时,它会被初始化,然后按照指定的顺序将其内容写入本机地址。
但我遇到的唯一问题是收集成员以作为参数传递给第 i 个 addFunction
因为编译器在这里报错:
members[i] = member.get(this)
Error:(328, 37) Kotlin: Out-projected type 'KProperty1' prohibits the use of 'public abstract fun get(receiver: T): R defined in kotlin.reflect.KProperty1'
我该如何解决?
这是一个继承问题。您的反射调用 this::class.declaredMemberProperties.find{ ... }
returns a KProperty1<out Bufferizable, Any?>
这意味着 属性 来自继承自 Bufferizable 的东西(有关 out
的更多信息,请参阅 declaration-site variance) .通过编译器不知道这个 属性 属于哪个 class 它不允许直接访问。要解决此问题,您必须访问 getter 函数:
members[i] = member.getter.call(this)
通过getter函数属于对象不属于反射api遵循默认的继承行为,可以调用