web-dev-qa-db-fra.com

Comment cloner un objet dans Kotlin?

La question est simple.

Documentation Kotlin décrit le clonage uniquement en accédant à Java et à la classe enum) . Dans ce dernier cas, le clone ne fait que lever une exception.

Alors, comment pourrais-je/devrais-je cloner un objet Kotlin arbitraire?

Devrais-je simplement utiliser clone() comme en Java?

25
Dims

Pour un data class, Vous pouvez utiliser la méthode générée par le compilateur copy() . Notez qu'il effectuera une copie superficielle.

Pour créer une copie d'une collection, utilisez les méthodes toList() ou toSet(), en fonction du type de collection dont vous avez besoin. Ces méthodes créent toujours une nouvelle copie d'une collection. ils effectuent également une copie superficielle.

Pour les autres classes, il n'y a pas de solution de clonage spécifique à Kotlin. Vous pouvez utiliser .clone() si cela répond à vos besoins, ou créer une solution différente si cela ne vous convient pas.

27
yole

Vous pouvez utiliser bibliothèque Gson pour convertir l'objet d'origine en chaîne, puis reconvertir cette chaîne en un type d'objet réel et vous obtiendrez un clone. Voir mon exemple. Placez cette fonction dans la classe/le modèle pour lequel vous voulez créer un clone. Dans mon exemple, je clone un objet de type Project . Je le mets donc dans le projet classe

class Project{
 fun clone(): Project {
                val stringProject = Gson().toJson(this, Project::class.Java)
                return Gson().fromJson<Project>(stringProject, Project::class.Java)
            }
}

Ensuite, utilisez-le comme ceci:

val originalProject = Project()
val projectClone = originalProject.clone()
11
zulkarnain shah

Cela nécessite d’implémenter Cloneable pour votre classe, puis écrasez clone () en tant que public comme:

public override fun clone(): Any {<your_clone_code>}

https://discuss.kotlinlang.org/t/how-to-use-cloneable/2364/

1
giang nguyen

J'ai voté pour la réponse de @yole for Nice, mais par d'autres moyens si vous n'utilisez pas (ou ne pouvez pas) utiliser la classe de données. Vous pouvez écrire une méthode d'assistance comme ceci:

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
        }
    }

}

Vous pouvez donc "copier" l'instance A dans B en:

val bInstance = AClassType()
ModelHelper.mergeFields(aInstance, bInstance)

Parfois, j’utilise cette méthode pour fusionner des données provenant de nombreuses instances en un seul objet dont la valeur est disponible (et non null).

0
dphans