Ответ 1
Рекомендуемый способ - написать toString
вручную (или сгенерировать по IDE) и надеяться, что у вас не так много таких классов.
Цель data class
- разместить наиболее распространенные случаи 85%, что оставляет 15% для других решений.
У меня есть класс с полями lateinit, поэтому они отсутствуют в конструкторе:
class ConfirmRequest() {
lateinit var playerId: String
}
Мне бы хотелось иметь метод toString() со всеми полями и не хочу писать его вручную, чтобы избежать печати котла. Если бы я использовал Java, я бы использовал аннотацию Lombok @ToString
для этой проблемы. Есть ли способ реализовать его в Котлин?
Рекомендуемый способ - написать toString
вручную (или сгенерировать по IDE) и надеяться, что у вас не так много таких классов.
Цель data class
- разместить наиболее распространенные случаи 85%, что оставляет 15% для других решений.
Как и вы, я использовал для использования lombok для toString()
и equals()
в Java, поэтому было немного разочаровано, что классы без данных в Kotlin потребовали все стандартные шаблоны.
Итак, я создал Kassava, библиотеку с открытым исходным кодом, которая позволяет реализовать toString()
и equals()
без каких-либо шаблонов - просто поставьте список свойств, и все готово!
Например:
// 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)
}
Я нашел Apache Commons Lang ToStringBuilder
с полезным отражением, но он вызывает hashCode()
и другие методы, когда мне это не нужно (и один из них называется hashCode()
из стороннего lib генерирует NPE).
Итак, я просто перейду с помощью
// class myClass
override fun toString() = MiscUtils.reflectionToString(this)
// class MiscUTils
fun reflectionToString(obj: Any): String {
val s = LinkedList<String>()
var clazz: Class<in Any>? = obj.javaClass
while (clazz != null) {
for (prop in clazz.declaredFields.filterNot { Modifier.isStatic(it.modifiers) }) {
prop.isAccessible = true
s += "${prop.name}=" + prop.get(obj)?.toString()?.trim()
}
clazz = clazz.superclass
}
return "${obj.javaClass.simpleName}=[${s.joinToString(", ")}]"
}
Вы можете определить класс данных, который содержит данные, которые вы хотите использовать, и реализовать методы, делегируя это.