Data class inheritance


#1

Why can not I inherit a lot of data class from another data class, in my case in the set of data classes there are several identical fields and I want to put them in a separate class and inherit from it, but the Kotlin does not allow it.

General class

@XmlAccessorType(XmlAccessType.PROPERTY)
data class Model(@XmlElement var name: StringProperty, @XmlElement var id: StringProperty) {

    constructor() : this(SimpleStringProperty(), SimpleStringProperty())

    fun getName(): String {
        return name.get()
    } 

    fun setName(name: String) {
        this.name.set(name)
    }

    fun getId(): String {
        return id.get()
    } 

    fun setId(name: String) {
        this.id.set(name)
    }
}

//@XmlAccessorType(XmlAccessType.PROPERTY)
//open class Model(@XmlElement var name: StringProperty, @XmlElement var id: StringProperty) {
//
//    constructor() : this(SimpleStringProperty(), SimpleStringProperty())
//
//    fun getName(): String {
//        return name.get()
//    }
//
//    fun setName(name: String) {
//        this.name.set(name)
//    }
//
//    fun getId(): String {
//        return id.get()
//    }
//
//    fun setId(name: String) {
//        this.id.set(name)
//    }
//}

Other class

@XmlRootElement
@XmlAccessorType(XmlAccessType.PROPERTY)
data class MyOtherData(@XmlElement val service: StringProperty) : Model() {

    constructor() : this(SimpleStringProperty())

    fun getService(): String {
        return service.get()
    }

    fun setService(service: String) {
        this.service.set(service)
    }
}

In the future, I need to copy the data class and serialize it in Xml, to save it to a file.

Xml serializer

object Xml {

    fun serialize(value: Any): String {

        val context = JAXBContext.newInstance(value::class.java)

        val marshaller = context.createMarshaller()

        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true)

        StringWriter().use { stream ->

            marshaller.marshal(value, stream)

            return stream.toString()
        }
    }

    fun <T> deserialize(value: String, clazz: Class<T>): T = StringReader(value).use { stream -> return JAXB.unmarshal(stream, clazz) }
}

Main.kt

val model = MyOtherData()

model.setService("OTHER_SERVICE")

model.setName("OTHER_NAME")

model.setId("3fad6db0ae684a0699c8ff0898e46d55")


// serialization/deserialization XML

val xml: String = Xml.serialize(model)

println(xml)

val des = Xml.deserialize(xml, MyOtherData::class.java)


val copy = model.copy()

println(copy.getService())

println(copy.getName())

println(copy.getId())

Can make a copy through serialization/deserialization, but i thought the data classes can be inherited.


#2

You can inherit a data class from a non-data class. Inheriting a data class from another data class is not allowed because there is no way to make compiler-generated data class methods work consistently and intuitively in case of inheritance.


#3

If I inherit from a class, copying does not work correctly, no properties are copied that are in a class other than data


#4

Yes, that’s correct. It’s impossible to generate a copy() method that could copy the properties of a non-data class, because there is no way to establish the correspondence between constructor parameters and properties.


#5

Ok, I understand you, then I’ll have to use this

object Xml {

    ...

    fun <T> copy(value: Any, clazz: Class<T>): T = deserialize(serialize(value), clazz)
}

Thanks for the help.