es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Reflexión de Kotlin Android para obtener la clase en tiempo de ejecución.

Tengo una respuesta del servidor que me devuelve diferentes objetos y cada objeto tiene un tipo. ¿Cómo puedo coincidir una clase en tiempo de ejecución con el tipo que recibo de la respuesta? Este código, por ejemplo, funciona, pero estoy tratando de deshacerme del enunciado “when” y hacerlo más dinámico.

“`kotlin
sealed class Tile(
private val id: String,
private val type: String,
private val title: String,
) {
class RedTile(
id: String,
type: String,
title: String,
val stuff: String
) : Tile(id, type, title) {
companion object {
const val TYPE = "RedTile"
}
}
class BlueTile(
id: String,
type: String,
title: String,
val value: Int
) : Tile(id, type, title) {
companion object {
const val TYPE = "BlueTile"
}
}
}

companion object {
fun parseArray(jsonArrayString: String): List<tile> {
return JsonParser.parseString(jsonArrayString).asJsonArray
.map { tileJsonObject ->
tileJsonObject as JsonObject
val tile = when (tileJsonObject.get("type").asString) {
Red.TYPE -> Red::class.java
Blue.TYPE -> Blue::class.java
else -> Red::class.java
}
Gson().fromJson(tileJsonObject, tile)
}
}
}
“`

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Un enfoque para volver el código más dinámico es mediante el uso de la reflexión en Kotlin. La reflexión es una herramienta poderosa que permite inspeccionar y modificar las propiedades de una clase y objetos en tiempo de ejecución. En este caso, se puede utilizar para obtener la clase correspondiente al tipo recibido en la respuesta del servidor, sin la necesidad de utilizar un bloque when. Aquí está una versión actualizada de la clase Tile que utiliza reflexión:

    sealed class Tile(
        private val id: String,
        private val type: String,
        private val title: String,
    ) {
        companion object {
            fun parseArray(jsonArrayString: String): List<tile> {
                return JsonParser.parseString(jsonArrayString).asJsonArray
                    .map { tileJsonObject ->
                        tileJsonObject as JsonObject
                        val tileType = tileJsonObject.get("type").asString
                        val tileClass = Tile::class.sealedSubclasses
                            .find { it.objectInstance?.TYPE == tileType }
                            ?: throw IllegalArgumentException("Tipo de tile desconocido: $tileType")
                        Gson().fromJson(tileJsonObject, tileClass.java)
                    }
            }
        }
    }
    
    object Red : Tile("id", "RedTile", "title") {
        const val TYPE = "RedTile"
    }
    
    object Blue : Tile("id", "BlueTile", "title") {
        const val TYPE = "BlueTile"
    }
    

    En este código actualizado, la clase Tile ha sido simplificada para contener únicamente las propiedades y el objeto compañero con el método parseArray. En lugar de definir las clases tiles como clases anidadas, se definen como objetos separados que heredan de Tile. Cada objeto tiene un campo constante TYPE que coincide con el tipo recibido en la respuesta del servidor.

    El método parseArray ahora utiliza reflexión para encontrar la clase correspondiente al tipo de tile. Lo hace llamando a la propiedad sealedSubclasses de la clase Tile::class, que devuelve una lista de todas las subclases de Tile declaradas en el mismo archivo. Luego filtra esta lista usando una lambda que verifica el campo TYPE de la instancia de objeto contra el tipo de tile recibido.

    Una vez que se encuentra la clase de tile, se pasa como argumento al método Gson().fromJson, que mapea automáticamente las propiedades JSON a las propiedades de la clase.

    Tenga en cuenta que este código supone que hay una correspondencia uno a uno entre los tipos de tile recibidos en la respuesta del servidor y las clases de tile definidas en el código. Si esto no es así, se debe agregar una manipulación de errores adicional.

Comments are closed.