【问题标题】:How to instantiate model class from nested classes with kotlin reflection如何使用 kotlin 反射从嵌套类中实例化模型类
【发布时间】:2021-03-10 06:43:24
【问题描述】:

我似乎无法理解 Kotlin 的反射文档。

我有一堆实现接口的嵌套类,所以它们都有相同的方法和属性。我想在 RecyclerView 中显示这些类中的每一个。我快到了,但我无法从我的类中获取信息来构建将在 RecyclerAdapter 中使用的模型类。

我得到了嵌套类的列表,但我不知道如何访问属性以便实例化模型。

这是我的界面:

interface SquibCommand {
    val title: String
    val description: String
    fun setParams(commandParams: CommandParams)
    fun execute()
}

然后我可以像这样得到所有嵌套类的集合:

val commandClass = AllCommands::class
val commandList = commandClass.nestedClasses
Log.d("Commands", "Your command collection is " + commandList)

然后我需要从每个命令构建一个模型,该模型可用于填充我的适配器视图中的字段。比如:

commandModels = ArrayList<CommandModel>
commandList.forEach {
   val cmd: CommandModel
   cmd.title = it.title 
   cmd.description = it.description 
   commandModels.add(cmd)
}

我似乎无法弄清楚如何从每个类中获取 title 和 description 属性的实际值,而不仅仅是属性的名称。

编辑:

所以我可以通过以下方式访问任何单个类的属性:

    val myOtherClass = AllCommands.TimerCommand::class.members.find {it.name == "title"}
    Log.d("BrowseCommands", "Your commands list is " + myOtherClass!!.call(AllCommands.TimerCommand()))

但是由于我必须访问集合中的所有嵌套类,所以我无法弄清楚要传递给 Call 的内容......它肯定应该是这样的:

    val myClass = commandList.elementAt(0)
    Log.d("BrowseCommands", "Your commands list is " + myClass.members.find {it.name == "title"}?.call(myClass()))

但这不起作用。当类来自 commandList 集合时,如何实例化该类?

【问题讨论】:

  • 如果您没有这些类的实例,您如何拥有titledescription 的值?你实际上会展示什么?
  • 在每个类中设置属性:即覆盖val title: String = "My Unique Title"
  • 由于这里给出的原因,无法检索默认表达式:discuss.kotlinlang.org/t/kotlin-reflection-and-default-values/… 这些属性的实现可能实际上是常量,但它们作为字节码中的表达式存在。
  • 那是函数参数,不是类属性。在此示例中检索了一个属性:stackoverflow.com/questions/58351219/… 但这是针对单个类的,因为我有一个嵌套类的集合,所以我传递给 call() 的任何内容似乎都不起作用。
  • 是的,但我认为同样的推理也适用。属性初始化器中= 之后的代码是一个表达式,而不是一个常量值。当初始化类的实例时,计算表达式并将结果分配给支持字段。属性初始化器基本上是 init 块的简写,它们是在初始化时作为对象构造的一部分运行的代码块。

标签: android kotlin


【解决方案1】:

如果你关心的所有嵌套类都有空的构造函数,你可以这样做。您必须实例化一个实例才能从属性中读取值,因为您的属性初始化中的表达式无法通过反射访问。

val commandModels = commandList.mapNotNull { kClass ->
    val instance = kClass.constructors.firstOrNull { it.parameters.isEmpty() }
        ?.call() as SquibCommand?
    instance?.let { CommandModel(it.title, it.description) }
}

【讨论】:

  • 谢谢,如果可行,请尝试一下并投票。只需要围绕一些不熟悉的术语和语法(我的大脑仍然无法应付 Lambas 哈哈)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多