1

In scala the parent class backing the case class is product : so we can use that for polymorphism across case classees. How can a similar goal be achieved for data classes in kotlin?

For the yaml parser below I would need a replacement for dataclass that represents a reasonable parent class of all data classes.

enter image description here

inline fun <reified T: dataclass> loadFromFileDC(path: Path): T  = loadFromFile(path, T::class)

 fun <T: dataclass> loadFromFile(path: Path, cls: KClass<T>) = {
    val mapper = ObjectMapper(YAMLFactory()) // Enable YAML parsing
    mapper.registerModule(KotlinModule()) // Enable Kotlin support

    Files.newBufferedReader(path).use {
        mapper.readValue(it, cls.java)
    }
}
WestCoastProjects
  • 58,982
  • 91
  • 316
  • 560
  • If I understood you correctly, I don't think it is possible in Kotlin. You can not inherit from data class, thus, there is no way to tell "This is a parent, I want all its children to be data class". – Michael Spitsin Apr 08 '20 at 05:26
  • @MichaelSpitsin Do `data clases` not have their _own_ inheritance hierarchy / parent class(es) that can work as a proxy for them? Even extending some `interface`s might work if those interfaces represent core `data class` behavior. – WestCoastProjects Apr 08 '20 at 05:27
  • No. Data classes are just ordinary classes with a bunch of predefined methods like "equals", "hashCode", etc. That's said you can inherit data class from sealed class, interface, any open or abstract class, but there is not data class specific hierarchy as far as I know. – Michael Spitsin Apr 08 '20 at 05:29
  • Huh. I had thought they were the `kotlin` equivalent of `case class`. Looks like not unfortunately. They do not even implement `serializable` which blew my mind. I'm skeptical about their usefulness. – WestCoastProjects Apr 08 '20 at 05:30
  • 2
    @MIchaelSpitsin btw feel free to make an answer. Just because it's not the answer I'd _prefer_ makes it no less of a valid one. – WestCoastProjects Apr 08 '20 at 05:32
  • According to serialization you may consider to take a look at this: https://github.com/Kotlin/kotlinx.serialization – Michael Spitsin Apr 08 '20 at 05:34
  • i could not get `kotlinx.serialization` to work even after extensive surgery on `build.gradle` . The implicit for the `data class`.serializer() does not work. – WestCoastProjects Apr 08 '20 at 05:36
  • Added answer :) – Michael Spitsin Apr 08 '20 at 06:17
  • I'll add that `Product` is not "the parent class backing the case class"; it's just a trait anyone can extend, so using it as a bound in `[T <: Product]` doesn't mean `T` is a case class. E.g. from the standard library it could be `Option` or `List`. – Alexey Romanov Apr 08 '20 at 21:13

1 Answers1

2

If I understood you correctly, I don't think it is possible in Kotlin. Data classes are just ordinary classes. Thus, you can inherit it from any open/abstract class, interface or sealed class. In the meantime, there is no way to inherit from data class, for instance, to force all children to be data class. And there is no data class-specific inheritance because as I mentioned data class is just an ordinary class with a predefined and pre-generated bunch of methods.

I think it is also worth thinking about it: Do you really need to identify every passed class as a data class at compile-time, and why you really need it?

If for instance, you want to apply any kind of polymorphism, then all you can use is just equals/hashCode/toString, because componenN and copy functions are just generated and have no base functions which they could override.

Since every class can implement those 3 methods. All you can do is to force implement them. For instance:

interface DataClass {
    override fun equals(other: Any?): Boolean
    override fun hashCode(): Int
    override fun toString(): String
}

data class Impl(val t: Int) : DataClass

In that case there is a high possibility that implementation will be forced to be data class, or it will be forced to provide all 3 needed methods. But this is hack rather than actual solution and you will not be able to apply that for 3rd-party-classes, since you will not be able to mark them with this interface.

In summary: I would recommend to think do you really need to know, is the clz from your example data class, or it can be anything. If yes, then you may consider to use reflection.

Please, see this: Is there a way to identify a Kotlin data class from a regular Kotlin class?

Michael Spitsin
  • 2,539
  • 2
  • 19
  • 29
  • They are not "just ordinary classes" because they can not support inheritance. And yes the issue is for third party libs that generate data class'es and not an extension of same. I am trying to find a general solution to the concern that -unbelievably - `data class`es do not implement `Serializable` . Using `kotlinx.serializable` is an extra burden and actually is not even working presently. – WestCoastProjects Apr 08 '20 at 06:21
  • 2 years later .. I had to drop _kotlin_ as a promising route because it had too many gotchas- this was one of them. Doubtful i'll have an opportunity to revisit since I veered even more sharply into data science that mostly is in the under-powered _python_ and afaict no intersection with _kotlin_ – WestCoastProjects Jul 24 '22 at 04:26