生成toString方法来包含基类的成员?

我正在尝试在Kotlin中构建一个DTO(数据传输对象)类,以便从Java应用程序调用。 鉴于以下代码:

BaseDto.kt

package sandbox.KotlinDataObjects import org.apache.commons.lang3.builder.ToStringBuilder import java.sql.ResultSet import java.sql.SQLException /** * Base DTO * (JSON/XML serialization code removed for clarity) */ abstract class BaseDto( var id: Long = 0 ) { @Throws(SQLException::class) open protected fun fromResultSet(rs: ResultSet) { this.id = rs.getLong("id") } /** * Override toString and use StringBuilder * Since DataObject may be one of many objects based on BaseDto * we want to avoid doing this in every data class * Derived class seems to generate a toString and this never gets * called, this is the issue I believe */ override fun toString(): String { return ToStringBuilder.reflectionToString(this) } } 

DataObject.kt

 package sandbox.KotlinDataObjects import org.apache.commons.lang3.builder.ToStringBuilder import java.sql.ResultSet data class DataObject( var name: String = "" ) : BaseDto() { override fun fromResultSet(rs: ResultSet) { super.fromResultSet(rs) name = rs.getString("name") } } 

Main.java

 package sandbox.KotlinDataObjects; import org.mockito.Mockito; import java.sql.ResultSet; import java.sql.SQLException; public class Main { /** * Mock ResultSet for testing with columns we are requesting * @return ResultSet * @throws SQLException */ private static ResultSet getMockedResultSet() throws SQLException { ResultSet mockedRs = Mockito.mock(ResultSet.class); Mockito.when(mockedRs.getLong("id")).thenReturn(12L); Mockito.when(mockedRs.getString("name")).thenReturn("MyName"); return mockedRs; } public static void main(String[] args) { try (ResultSet mockedRs = getMockedResultSet()) { // Read DataObject from ResultSet (mocked to avoid DB connection) DataObject dobj = new DataObject(); dobj.fromResultSet(mockedRs); System.out.println("toString: dobj="+dobj); System.out.println("getters: dobj.name="+dobj.getName()+" dobj.id="+dobj.getId()); } catch (SQLException e) { e.printStackTrace(); } } } 

这显示:

 toString: dobj2=DataObject(name=MyName) getters: dobj2.name=MyName dobj2.id=12 

我想在DataObject.toString调用中包含BaseDto的id字段。 一种选择是在DataObject.toSting中用ToStringBuilder.reflectionToString重写toString,但是它必须被添加到派生自BaseDto的每个对象。 有没有办法来声明一个数据对象的层次结构,自动包含来自基类的成员。 这在java中是可行的,通过在基础中覆盖toString()并使用Kotlin中的ToStringBuilder.reflectionToString,基础toString不会被调用,因为数据对象会生成自己版本的toString而不会调用super。

使用反射调用覆盖BaseDto toString ,如下所示(对于reflectionToString()代码示例, 信用于@junique )…

 import kotlin.reflect.* import kotlin.collections.* import java.lang.reflect.Modifier abstract class BaseDto( var id: Long = 0L ) { open protected fun fromResultSet(rs: ResultSet) { this.id = rs.id } override open public fun toString() = reflectionToString(this) fun reflectionToString(obj: Any?): String { if(obj == null) { return "null" } val s = mutableListOf<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(", ")}]" } } 

编辑

我通过创建一个普通的class而不是一个data class来测试这个。 它不适用于data class 。 在1.1之前, data classes甚至不能扩展其他类(但是可以实现接口)。 我越来越同意OP。