Pourquoi choisir Kotlin ?

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:

  1. 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.
  2. 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
}
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s