1. La valeur en ligne d'une classe en ligne peut être implémentée par délégation
Si vous souhaitez créer un wrapper léger pour une instance de valeur ou de classe, vous devez implémenter toutes les méthodes d'interface manuellement. L'implémentation via des délégués résout ce problème, mais avant la version 1.7.0, cela ne fonctionnait pas dans les classes en ligne. Cette limitation a été supprimée, vous pouvez donc désormais créer des wrappers légers qui ne nécessitent pas d'allocation de mémoire dans la plupart des cas.
interface Bar {
fun foo() = "foo"
}
@JvmInline
value class BarWrapper(val bar: Bar): Bar by bar
fun main() {
val bw = BarWrapper(object: Bar {})
println(bw.foo())
}
2. L'opérateur de soulignement est utilisé pour les paramètres de type
Kotlin 1.7.0 introduit l'opérateur de soulignement _ pour les paramètres de type. Cela peut être utilisé pour déduire automatiquement les paramètres de type lorsque d'autres types sont spécifiés :
abstract class SomeClass<T> {
abstract fun execute(): T
}
class SomeImplementation : SomeClass<String>() {
override fun execute(): String = "Test"
}
class OtherImplementation : SomeClass<Int>() {
override fun execute(): Int = 42
}
object Runner {
inline fun <reified S: SomeClass<T>, T> run(): T {
return S::class.java.getDeclaredConstructor().newInstance().execute()
}
}
fun main() {
// T is inferred as String because SomeImplementation derives from SomeClass<String>
val s = Runner.run<SomeImplementation, _>()
assert(s == "Test")
// T is inferred as Int because OtherImplementation derives from SomeClass<Int>
val n = Runner.run<OtherImplementation, _>()
assert(n == 42)
}
Les paramètres de type peuvent être déduits à l’aide de l’opérateur de soulignement n’importe où dans une liste de variables.
3. Inférence du générateur de version stable
L'inférence de générateur est un type spécial d'inférence de type qui est utile lors de l'appel de fonctions de générateur génériques. Cela aide le compilateur à déduire les paramètres de type d'un appel en utilisant les informations de type provenant d'autres appels dans les paramètres lambda.
À partir de la version 1.7.0, l'inférence du générateur est automatiquement activée si l'inférence de type standard ne peut pas obtenir suffisamment d'informations sur le type sans spécifier l'option du compilateur -Xenable-builder-inference (introduite dans la version 1.6.0).
Apprenez à écrire des constructeurs génériques personnalisés .
4. Exigences d'adhésion à la version stable
Depuis la version 1.7.0, les exigences d'adhésion de Kotlin ont été stabilisées et aucune configuration supplémentaire du compilateur n'est requise.
Avant la version 1.7.0, la fonctionnalité Opt-in elle-même nécessitait le paramètre -opt-in=kotlin.RequiresOptIn pour éviter les avertissements. Cela n'est plus nécessaire ; cependant, vous pouvez toujours utiliser le paramètre du compilateur -opt-in pour sélectionner d'autres annotations à inscrire, ciblant l'ensemble du module.
5. La version stable ne doit pas être de type vide
Dans Kotlin 1.7.0, les types explicites non nuls ont été promus au rang de fonctionnalité de stabilité. Ils offrent une meilleure interopérabilité lors de l’extension des classes et interfaces Java génériques.
Vous pouvez utiliser la nouvelle syntaxe T & Any pour marquer les paramètres de type comme explicitement non nuls lors de leur utilisation. Cette forme syntaxique provient de la notation des types d'intersection, désormais contraints d'avoir un paramètre de type avec une limite supérieure nullable à gauche de & et un Any non nul à droite :
fun <T> elvisLike(x: T, y: T & Any): T & Any = x ?: y
fun main() {
// OK
elvisLike<String>("", "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String>("", null).length
// OK
elvisLike<String?>(null, "").length
// Error: 'null' cannot be a value of a non-null type
elvisLike<String?>(null, null).length
}
6. Bibliothèque standard
Dans Kotlin 1.7.0, la bibliothèque standard a reçu une série de modifications et d'améliorations. Ils introduisent de nouvelles fonctionnalités, stabilisent les fonctionnalités expérimentales et unifient la prise en charge des groupes de capture nommés dans Native, JS et JVM :
- Les fonctions d'agrégation min() et max() renvoient des valeurs non nullables
- Correspondance d'expression régulière à la position d'index spécifiée
- Prise en charge étendue des langues précédentes et des versions d'API
- Accéder aux annotations via la réflexion
- Version stable de la fonction récursive profonde
- L'horodatage de la source de temps par défaut est basé sur une classe en ligne
- Nouvelles fonctions d'extension expérimentales pour Java Facultatif
- Prise en charge de la capture nommée sur les plateformes JS et natives