Kotlin est un langage de programmation à typage statique sponsorisé et développé par JetBrains qui s’exécute sur la machine virtuelle Java et peut également être compilé en code source JavaScript ou utiliser l’infrastructure de compilateur LLVM.
Voici quelques raisons pour lesquelles vous devriez basculer totalement vers Kotlin ( référence ):
0. Interopérabilité Java
Kotlin est 100% interopérable avec Java. Vous pouvez littéralement continuer à travailler sur vos anciens projets Java avec Kotlin. Tous vos frameworks Java préférés sont toujours disponibles, et quel que soit le framework que vous écrivez dans Kotlin, il est facilement adopté par votre ami Java.
1. Syntaxe familière
Le kotlin n’est pas une langue étrange née dans le monde universitaire. Sa syntaxe est familière à tout programmeur issu du domaine de la programmation orientée objet et peut être plus ou moins comprise dès le départ. Il existe bien sûr quelques différences avec Java, telles que les constructeurs retravaillés ou les déclarations de variables val var. L’extrait ci-dessous présente la plupart des bases:
class Foo {
val b: String = “b” // val = variable qu’on ne peut pas modifier
var i: Int = 0 // var = variable modifiable
fun hello() {
val str = “Hello”
print(“$str World”)
}
fun sum(x: Int, y: Int): Int {
return x + y
}
fun maxOf(a: Float, b: Float) = if (a > b) a else b
}
2. Interpolation de chaîne
C’est comme si une version plus intelligente et plus lisible de Java, String.format () était intégrée au langage:
val x = 4
val y = 7
print(“sum of $x and $y is ${x + y}”) // addition de 4 et 7 est 11
3. Type Inference
Kotlin déduira vos types partout où vous pensez que cela améliorera la lisibilité:
val a = “abc” // type inféré à String
val b = 4 // type inféré à Int
val c: Double = 0.7 // type déclaré explicitement
val d: List = ArrayList() // type déclaré explicitement
4. Casts intélligents
Le compilateur Kotlin suit votre logique et, si possible, les types de conversions automatiques, ce qui signifie qu’il n’y a plus d’instance de vérifications suivie de distributions explicites:
if (obj is String) {
print(obj.toUpperCase()) // obj maintenant est reconnu comme un objet String
}
5. Égal intuitif
Vous pouvez arrêter d’appeler explicitement equals(), car l’opérateur == vérifie maintenant l’égalité structurelle:
val john1 = Person(“John”)
val john2 = Person(“John”)
john1 == john2 // true (égalité structurelle)
john1 === john2 // false (égalité structurelle)
6. Arguments par défaut
Pas besoin de définir plusieurs méthodes similaires avec des arguments différents:
fun build(title: String, width: Int = 800, height: Int = 600) {
Frame(title, width, height)
}
7. Arguments nommés
Combinés aux arguments par défaut, les arguments nommés éliminent le besoin de générateurs:
build(“MarioBros”, 700, 400) // équivalent
build(title = “MarioBros”, width = 700, height = 400) // équivalent
build(width = 700, height = 400, title = “MarioBros”) // équivalent
8. L’expression When
Le boîtier du commutateur est remplacé par l’expression beaucoup plus lisible et flexible:
when (x) {
1 -> print(“x is 1”)
2 -> print(“x is 2”)
3, 4 -> print(“x is 3 or 4”)
in 5..10 -> print(“x is 5, 6, 7, 8, 9, or 10”)
else -> print(“x is out of range”)
}
Cela fonctionne à la fois comme une expression ou une déclaration et avec ou sans un argument:
val res: Boolean = when {
obj == null ->false
obj is String -> true
else -> throw IllegalStateException()
}
9. Propriétés
Un ensemble personnalisé et un comportement peuvent être ajoutés aux champs publics, ce qui signifie que nous pouvons arrêter de gonfler notre code avec des getters et des setters insensés.
class Frame {
var width: Int = 800
var height: Int = 600
val pixels: Int
get() = width * height
}
10. The Data Class
C’est un POJO complet avec toString(), equals(), hashCode() et copy(), et contrairement à Java, il ne prendra pas 100 lignes de code:
data class Person(val name: String, var email: String, var age: Int)
val john = Person(“John”, “john@gmail.com”, 112)
11. Surcharge de l’opérateur
Un ensemble prédéfini d’opérateurs peut être surchargé pour améliorer la lisibilité:
data class Vec(val x: Float, val y: Float) {
operator fun plus(v: Vec) = Vec(x + v.x, y + v.y)
}
val v = Vec(2f, 3f) + Vec(4f, 1f)
12. Déclarations de destructuration
Certains objets peuvent être déstructurés, ce qui est par exemple utile pour itérer des map:
for ((key, value) in map) {
print(“Key: $key”)
print(“Value: $value”)
}
13. Ranges
Par souci de lisibilité:
for (i in 1..100) { … }
for (i in 0 until 100) { … }
for (i in 2..10 step 2) { … }
for (i in 10 downTo 1) { … }
if (x in 1..10) { … }
14. Fonctions d’extension
Rappelez-vous la première fois que vous avez dû trier une liste en Java? Comme vous ne pouviez pas trouver une fonction sort(), vous deviez demander à votre tuteur ou à Google de se renseigner sur Collections.sort (). Et plus tard, lorsque vous avez dû mettre en majuscule une chaîne, vous avez fini par écrire votre propre fonction d’assistance car vous ne connaissiez pas StringUtils.capitalize().
Si seulement il y avait un moyen d’ajouter de nouvelles fonctions aux anciennes classes; De cette façon, votre IDE pourrait vous aider à trouver la bonne fonction dans la complétion de code. Avec Kotlin vous pouvez faire exactement ça:
fun String.replaceSpaces(): String {
return this.replace(‘ ‘, ‘_’)
}
val formatted = str.replaceSpaces()
La bibliothèque standard étend les fonctionnalités des types originaux de Java, ce qui était particulièrement nécessaire pour String:
str.removeSuffix(“.txt”)
str.capitalize()
str.substringAfterLast(“/”)
str.replaceAfter(“:”, “classified”)
15. Null Safety
Java est ce que nous devrions appeler un langage typé de manière quasi statique. Dans ce document, une variable de type String ne garantie pas une référence à une chaîne – elle peut faire référence à null. Même si nous sommes habitués à cela, cela réduit à néant la sécurité de la vérification de type statique et oblige aux développeurs Java à vivre dans la peur constante des NPE ( Non-Permissive Environment Contents ).
Kotlin résout ce problème en distinguant les types non null et les types nullable. Les types ne sont pas nuls par défaut et peuvent être rendus nuls en ajoutant un ? Comme ceci:
var a: String = “abc”
a = null // compile error
var b: String? = “xyz”
b = null // pas de problème
Kotlin vous oblige à vous prémunir contre les NPE lorsque vous accédez à un type nullable:
val x = b.length // compile error: b peut-être null
Et même si cela peut sembler fastidieux, c’est vraiment un jeu d’enfant grâce à quelques-unes de ses fonctionnalités. Nous avons toujours des distributions intelligentes, qui convertissent les types nullable en non-null chaque fois que c’est possible:
if (b == null) return
val x = b.length // pas de problème
Nous pourrions également utiliser un appel sécurisé ?., Qui renvoie null au lieu de lancer un NPE:
val x = b?.length // type de x est nullable Int
Les appels sécurisés peuvent être chaînés pour éviter ces vérifications imbriquées si-non-null, nous écrivons parfois dans d’autres langues, et si nous voulons une valeur par défaut autre que null, nous pouvons utiliser l’opérateur ?: :
val name = ship?.captain?.name ?: “unknown”
Si rien de tout cela ne fonctionne pour vous et que vous avez absolument besoin d’un NPE, vous devrez le demander explicitement:
val x = b?.length ?: throw NullPointerException() // le même que celui au dessous
val x = b!!.length // le même que celui au dessus
16. Des meilleurs Lambdas
Très bon système lambda, parfaitement équilibré entre lisibilité et nuance, grâce à des choix de conception astucieux. La syntaxe est d’abord simple:
val sum = { x: Int, y: Int -> x + y } // type: (Int, Int) -> Int
val res = sum(4,7) // res == 11
Et voici les astuces:
- Les parenthèses de méthode peuvent être déplacées ou omises si le lambda est le dernier ou le seul argument d’une méthode.
- Si nous choisissons de ne pas déclarer l’argument d’un seul argument-lambda, il sera déclaré implicitement sous le nom it.
Ces faits combinés rendent les trois lignes suivantes équivalentes:
numbers.filter({ x -> x.isPrime() })
numbers.filter { x -> x.isPrime() }
numbers.filter { it.isPrime() }
Et cela nous permet d’écrire un code fonctionnel concis – il suffit de regarder cette beauté:
persons
.filter { it.age >= 18 }
.sortedBy { it.name }
.map { it.email }
.forEach { print(it) }
Le système lambda de Kotlin associé à des fonctions d’extension le rend idéal pour la création DSL. Exemple:
verticalLayout {
padding = dip(30)
editText {
hint = “Name”
textSize = 24f
}
editText {
hint = “Password”
textSize = 24f
}
button(“Login”) {
textSize = 26f
}
}