1

Hi I'm trying to create a generic function to make a deep copy of list using the copy() method that a Data class provide us.

I'm using the method that I found on other post which returns a list of objects being deep copied:

listDataClass.map{ it.copy() }

But I can't seem to know how to make it as a generic function for data class so I'm really curious to see how'd you make one like this.

Barrufet
  • 495
  • 1
  • 11
  • 33
  • 2
    This can’t be done with generics because data classes don’t share a superclass with a `copy` method. You would have to use reflection, and it wouldn’t be able to identify at compile time whether your list contains data class instances or not. – Tenfour04 Jan 04 '21 at 13:24
  • Oh that's sad but makes sense, thank you for your answer! You can post it and I'll give you the correct answer :) – Barrufet Jan 04 '21 at 15:17

1 Answers1

3

By using kotlin reflection magic, you can do it like this:

class NotADataClassException(clazz: KClass<out Any>): Exception("$clazz is not a data class")

fun List<T>.deepCopy(): List<T> {
    return map { item ->
        if (!item::class.isData) {
            throw NotADataClassException(item::class)
        } else {
            item::class.members.first { it.name == "copy" }.callBy(emptyMap()) as T
        } 
    }
}

However, this is bad because of the following reasons:

  • This doesn't constrain the elements to data classes at compile time (that is what we wanted to do with the generics!) instead, it throws an exception.

  • Kotlin reflection is slow and big, and reflection is used for every item.

Deadbeef
  • 1,499
  • 8
  • 20