The question is that simple.
Kotlin documentation describes cloning only in accessing Java and in enum class. In latter case clone is just throwing an exception.
So, how would I / should I clone arbitrary Kotlin object?
Should I just use clone()
as in Java?
For a data class
, you can use the compiler-generated copy()
method. Note that it will perform a shallow copy.
To create a copy of a collection, use the toList()
or toSet()
methods, depending on the collection type you need. These methods always create a new copy of a collection; they also perform a shallow copy.
For other classes, there is no Kotlin-specific cloning solution. You can use .clone()
if it suits your requirements, or build a different solution if it doesn't.
You can use Gson to convert the original object to a String and then convert back that String to an actual Object type, and you'll have a clone. See my example. Put this function in the class/model of which you want to create a clone. In my example I'm cloning a Project type object so I'll put it in the Project class
class Project{
fun clone(): Project {
val stringProject = Gson().toJson(this, Project::class.java)
return Gson().fromJson<Project>(stringProject, Project::class.java)
}
}
Then use it like this:
val originalProject = Project()
val projectClone = originalProject.clone()
I've voted for @yole for nice answer, but other ways if you don't (or can't) use data class. You can write helper method like this:
object ModelHelper {
inline fun <reified T : Serializable> mergeFields(from: T, to: T) {
from::class.java.declaredFields.forEach { field ->
val isLocked = field.isAccessible
field.isAccessible = true
if (field.get(from) != null) {
field.set(to, field.get(from))
}
field.isAccessible = isLocked
}
}
}
So you can "copy" instance A into B by:
val bInstance = AClassType()
ModelHelper.mergeFields(aInstance, bInstance)
Sometimes, I use this way to merge data from many instances into one object which value available (not null).