【问题标题】:What is the easiest way to print a Kotlin data class as compilable code?将 Kotlin 数据类打印为可编译代码的最简单方法是什么?
【发布时间】:2019-09-12 22:15:40
【问题描述】:

我希望能够将一个相当简单的 Kotlin 数据类的实例转换为可以复制并粘贴到 Kotlin 文件中并可以编译的字符串。

例如,给定这些数据类:

data class Parent(val name: String, val age: Int, val children: Set<Child>)
data class Child(val name: String, val age: Int)

我想要一个从任何数据类到 String 的函数,这样:

toCompilableString(
   Parent("Joe", 34, setOf(Child("Amy", 4), Child("Bob", 7)))
)

会返回

"""Parent("Joe", 34, setOf(Child("Amy", 4), Child("Bob", 7)))"""

这样的事情存在吗?

【问题讨论】:

  • 我当然可以手动滚动一些东西,我希望已经有一个库函数可以为我做这件事。

标签: kotlin


【解决方案1】:

我们可以覆盖 toString 的行为,以所需的格式输出:

fun main() {
    var amy = Child(name="Amy",age=4)
    var bob = Child(name="Bob",age=7)
    var joe = Parent(name="Joe", age=34, children=setOf(amy, bob))

    print(joe) // outputs "Parent("Joe", 34, setOf(Child("Amy", 4), Child("Bob", 7))"
}

data class Parent(val name: String, val age: Int, val children: Set<Child>) {
    override fun toString() = "Parent(\"$name\", $age, setOf(${children.joinToString()})"
}
data class Child(val name: String, val age: Int) {
    override fun toString() = "Child(\"$name\", $age)"
}

joinToString()的帮助下,这将以"Parent("Joe", 34, setOf(Child("Amy", 4), Child("Bob", 7))"的格式输出。

【讨论】:

  • 很好,尽管您缺少字符串周围的引号。但我正在寻找通用的东西,而不是必须在每个数据类上覆盖 toString。
【解决方案2】:

如果你真的很喜欢疼痛,有专门为这类事情制作的反射工具。我做了一个小函数,可以生成你需要的东西:

fun dataClassToString(instance: Any) {
    val sb = StringBuilder()
    sb.append("data class ${instance::class.qualifiedName} (")
    var prefix = ""
    instance::class.memberProperties.forEach{
        sb.append(prefix)
        prefix = ","
        sb.append("${it.name} = ${it.getter.call(instance)}")
    }
    sb.append(")")
    println(sb.toString())
}

这个函数的唯一问题是它会为你的父类生成以下内容:

data class Parent (age = 34,children = [Child(name=Amy, age=4), Child(name=Bob, age=7)],name = Joe)

内部集合表示为数组,但是如果您确定您将只有集合或数组,您可以轻松检查它是什么类型并在创建集合时附加该类型。您还可以检查这是否是一个数据类并附加它而不是硬编码字符串。

【讨论】:

    猜你喜欢
    • 2021-11-11
    相关资源
    最近更新 更多