¿Se ha generado el método toString para include miembros de la class base?

Estoy tratando de crear una class DTO (data-transfer-object) en Kotlin para ser llamado desde una aplicación Java. Dado el siguiente código:

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(); } } } 

Esto muestra:

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

Me gustaría include el campo de Id del BaseDto en la llamada DataObject.toString. Una opción es anular toString con ToStringBuilder.reflectionToString en DataObject.toSting, pero debería agregarse a cada object derivado de BaseDto. ¿Hay alguna forma de declarar una jerarquía de objects de datos que incluya automáticamente miembros de classs base? Esto es factible en Java sobrescribiendo toString () en la base y usando ToStringBuilder.reflectionToString, en Kotlin no se llama a la base toString ya que el object de datos genera su propia versión de toString que no llama a super.

Anular toString en BaseDto con una llamada de reflexión como la siguiente ( crédito a @junique para el ejemplo del código reflectionToString() ) …

 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.declanetworkingFields.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(", ")}]" } } 

EDITAR

Probé esto creando una class regular en lugar de una data class . No funciona para una data class . Antes de 1.1, data classes no podían extender otras classs (pero podían implementar interfaces). Cada vez más, estoy de acuerdo con el OP.