<T> void f() {
System.out.println(T.class);
}
Et c'est parfois bien dommage. On ne peut pas non plus tester si un objet est une instance ou pas de T.
En Kotlin non plus... Sauf si on décide d'inliner la fonction, auquel cas le code est recopié dans la classe appelante, là où le type réel est connu :
inline fun <reified T> f() {
println (T::class)
}
Il faut ajouter le mot clef reified devant le type générique.
On peut imaginer plein d'utilisations réelles. Je vous propose un exemple concret. Voyons la version Java :
enum Genre {H, F} interface A { void f(Genre genre); } <E extends Enum<E>> E getEnum(BufferedReader r, Class<E> enumClass)
throws IOException { return Enum.valueOf(enumClass, r.readLine()); }
La fonction getEnum retourne un enum à partir d'une source, ici un flux de données, mais on peut utiliser une base de données, un objet swing ou une URL, avec un traitement d'erreur, et donc un code plus complexe qu'on souhaite partager, et qui justifie l'écriture de la fonction.
Pour appeler cette fonction on doit expliciter le type réel :
a.f(b.getEnum(reader, Genre.class));
En Kotlin, on peut faire plus simple :
enum class Genre {H, F }
interface A {
fun f(genre: Genre)
}
inline fun <reified E : Enum<E>> getEnum(r: BufferedReader): E {
return java.lang.Enum.valueOf<E>(E::class.java, r.readLine())
}
Le second paramètre a disparu et l'appel devient :
a.f(getEnum(reader))
Si la fonction est souvent utilisée, économiser un paramètre obligatoire alors qu'il peut-être déduit de l'environnement, ce n'est pas négligeable pour la lisibilité du code.
Aucun commentaire:
Enregistrer un commentaire