2017-06-17 3 views
4

J'ai une simple fonction d'aide pour obtenir la valeur de SharedPreferences comme ceci:Kotlin - Impossible d'utiliser 'T' comme paramètre de type réifié. Utilisez une classe à la place

operator inline fun <reified T : Any> SharedPreferences.get(key: String, defaultValue: T? = null): T? { 
    return when (T::class) { 
     String::class -> getString(key, defaultValue as? String) as T? 
     Int::class -> getInt(key, defaultValue as? Int ?: -1) as T? 
     Boolean::class -> getBoolean(key, defaultValue as? Boolean ?: false) as T? 
     Float::class -> getFloat(key, defaultValue as? Float ?: -1f) as T? 
     Long::class -> getLong(key, defaultValue as? Long ?: -1) as T? 
     else -> throw UnsupportedOperationException("Not yet implemented") 
    } 
} 

J'ai utilisé paramètre de type réifiée d'avoir commutation type de classe et comme il est une fonction de l'opérateur, je devrais être capable d'appeler avec la syntaxe carrée de crochets comme ci-dessous:

val name: String? = prefs[Constants.PREF_NAME] 

Mais, chaque fois que je l'appelle, est fonction UnsupportedOperationException indiquant ne peut pas propulsée vers d'obtenir le type de classe.

Quand j'attache débogueur et d'évaluer T::class, il me donne une erreur "Cannot use 'T' as reified type parameter. Use a class instead."

Quel est le problème avec ma fonction? Je ne pouvais pas attraper l'erreur. quelqu'un peut-il aider?

Éditer: Toute la classe est here et this is where Je reçois l'erreur.

Mise à jour: Il semble s'agir d'un problème de compilation Kotlin. Piste https://youtrack.jetbrains.com/issue/KT-17748 et https://youtrack.jetbrains.com/issue/KT-17748 pour les mises à jour.

+0

Je ne peux pas reproduire votre erreur. Une chose que je peux noter est que vous ne retournez pas le résultat de 'when', donc il retournera toujours null. –

+0

@JornVernee pouvez-vous s'il vous plaît voir ceci: https://gist.github.com/krupalshah/782c42c70f2c58004c9bbda6291315e6 J'ai besoin de votre aide. –

+0

Je ne peux pas vous aider si je ne peux pas reproduire l'erreur. –

Répondre

2

Le problème est curieux, mais il semble que Int::class n'est pas la même chose que Int?::class (ce qui est une expression illégale de toute façon).

Lorsque vous ajoutez la ligne:

println(T::class) 

Pour la méthode get et appelez val age: Int? = prefs["AGE", 23], vous verrez qu'il imprime java.lang.Integer. Il semble que Int? est traduit en java.lang.Integer.

Un possible (mais IMHO type de aki) solution est d'utiliser les références à des classes Java comme les cas lorsque:

operator inline fun <reified T : Any> get(key: String, defaultValue: T? = null): T? { 
    return when (T::class) { 
     String::class -> getString(key, defaultValue as? String) as T? 
     java.lang.Integer::class -> getInt(key, defaultValue as? Int ?: -1) as T? 
     java.lang.Boolean::class -> getBoolean(key, defaultValue as? Boolean ?: false) as T? 
     java.lang.Float::class -> getFloat(key, defaultValue as? Float ?: -1f) as T? 
     java.lang.Long::class -> getLong(key, defaultValue as? Long ?: -1) as T? 
     else -> throw UnsupportedOperationException("Not yet implemented") 
    } 
} 
+0

Merci. Tu as raison. La première solution fonctionne également bien maintenant. Avons-nous découvert un nouveau bug dans le compilateur Kotlin? –

+1

@KrupalShah Pas un bug, peut-être une lacune; qu'il n'a pas de traitement spécial en comparant 'java.lang.Integer :: class' à' Int :: class' –

+0

Hm .. ok. Votre deuxième solution est correcte mais le seul problème est que je devrais être capable de passer null comme valeur par défaut même si je veux une chaîne. Cette fois ça ne marchera pas. –