Kotlin - 为非数据类生成toString()

时间:2016-11-29 09:31:13

标签: java kotlin tostring

情况:

我有一个包含lateinit字段的类,因此它们不在构造函数中:

class ConfirmRequest() {
    lateinit var playerId: String
}

我想在所有字段中使用toString()方法并且不想手动编写,以避免打印锅炉。在Java中,我使用 Lombok @ToString注释来解决这个问题。

问题:

有没有办法在Kotlin中实现它?

6 个答案:

答案 0 :(得分:10)

推荐的方法是手动编写toString(或由IDE生成),并希望你没有太多这样的类。

data class的目的是容纳最常见的85%的案例,其中15%留给其他解决方案。

答案 1 :(得分:8)

和你一样,我习惯在Java中使用lombok for toString()equals(),所以有点失望的是Kotlin中的非数据类需要所有的标准样板。

所以我创建了Kassava,这是一个开源库,可让您实现toString()equals()而无需任何样板 - 只需提供属性列表即可完成!< / p>

例如:

// 1. Import extension functions
import au.com.console.kassava.kotlinEquals
import au.com.console.kassava.kotlinToString

import java.util.Objects

class Employee(val name: String, val age: Int? = null) {

    // 2. Optionally define your properties for equals()/toString() in a  companion
    //    object (Kotlin will generate less KProperty classes, and you won't have
    //    array creation for every method call)
    companion object {
        private val properties = arrayOf(Employee::name, Employee::age)
    }

    // 3. Implement equals() by supplying the list of properties to be included
    override fun equals(other: Any?) = kotlinEquals(
        other = other, 
        properties = properties
    )

    // 4. Implement toString() by supplying the list of properties to be included
    override fun toString() = kotlinToString(properties = properties)

    // 5. Implement hashCode() because you're awesome and know what you're doing ;)
    override fun hashCode() = Objects.hash(name, age)
}

答案 2 :(得分:8)

我发现Apache Commons Lang的"InconsistentNaming"反射很有用,但是当我不需要时,它会调用Rules.ReSharper和其他方法(以及一个名为ToStringBuilder的方法来自第三方lib生成NPE)。

所以我跟着:

hashCode()

答案 3 :(得分:1)

您可以定义一个包含您要使用的数据的数据类,并通过委托给它来实现方法。

https://stackoverflow.com/a/46247234/97777

答案 4 :(得分:0)

使用Kotlin反射怎么样?我在科特林呆了几天,如果我误解了问题或写了“科特林效率低下”的例子,我深表歉意。

override fun toString() : String{
    var ret : String = ""
    for (memberProperty in this.javaClass.kotlin.memberProperties){
        ret += ("Property:${memberProperty.name} value:${memberProperty.get(this).toString()}\n");
    }
    return ret
}

这也可以在新创建的接口中实现,例如toString2Interface作为ToString2Interface。然后所有实现ToString2Interface的类都将具有toString2()

答案 5 :(得分:0)

这就是我最终要做的。

Any类上创建扩展功能

fun Any.toStringByReflection(exclude: List<String> = listOf(), mask: List<String> = listOf()): String {
    val propsString = this::class.memberProperties
            .filter { exclude.isEmpty() || !exclude.contains(it.name) }
            .joinToString(", ") {
                val value = if (!mask.isEmpty() && mask.contains(it.name)) "****" else it.getter.call(this).toString()
                "${it.name}=${value}"
            };

    return "${this::class.simpleName} [${propsString}]"
}

然后您可以从单个类型调用此方法。

override fun toString(): String {
    return this.toStringByReflection()
}

它在下面生成字符串

Table [colums=[], name=pg_aggregate_fnoid_index, schema=pg_catalog, type=SYSTEM INDEX]

名称字段被屏蔽:

override fun toString(): String {
    return this.toStringByReflection(mask= listOf("name"))
}

它生成

Table [colums=[], name=****, schema=pg_catalog, type=SYSTEM INDEX]