Kotlin est un langage de programmation “pragmatique” à usage général, gratuit, open source, typé statiquement, initialement conçu pour la JVM (Java Virtual Machine) et Android, et combine des fonctionnalités de programmation orientées objet et fonctionnelles. Il est axé sur l’interopérabilité, la sécurité, la clarté et la prise en charge des outils. Des versions de Kotlin ciblant JavaScript ES5.1 et du code natif (utilisant LLVM) pour un certain nombre de processeurs sont également en production.
Kotlin est né chez JetBrains, la société derrière IntelliJ IDEA, en 2010, et est open source depuis 2012. Le Projet Kotlin sur GitHub compte plus de 770 contributeurs ; alors que la majorité de l’équipe travaille chez JetBrains, il y a eu près de 100 contributeurs externes au projet Kotlin. JetBrains utilise Kotlin dans plusieurs de ses produits, y compris son produit phare IntelliJ IDEA.
Kotlin comme langage Java plus concis
À première vue, Kotlin ressemble à une version plus concise et simplifiée de Java. Considérez la capture d’écran ci-dessus, où j’ai converti un exemple de code Java (à gauche) à Kotlin automatiquement. Notez que la répétition insensée inhérente à l’instanciation des variables Java a disparu. L’idiome Java
StringBuilder sb = new StringBuilder();
Devient en Kotlin
val sb = StringBuilder()
Vous pouvez voir que les fonctions sont définies avec le fun
mot-clé, et que les points-virgules sont désormais facultatifs lorsque des retours à la ligne sont présents. La val
Le mot-clé déclare une propriété en lecture seule ou une variable locale. De même, le var
Le mot-clé déclare une propriété mutable ou une variable locale.
Néanmoins, Kotlin est fortement typé. La val
et var
les mots-clés ne peuvent être utilisés que lorsque le type peut être déduit. Sinon, vous devez déclarer le type. L’inférence de type semble s’améliorer à chaque version de Kotlin.
Jetez un œil à la déclaration de fonction en haut des deux volets. Le type de retour en Java précède le prototype, mais en Kotlin il succède au prototype, délimité par deux-points comme en Pascal.
Ce n’est pas tout à fait évident à partir de cet exemple, mais Kotlin a assoupli l’exigence de Java selon laquelle les fonctions doivent être des membres de classe. Dans Kotlin, les fonctions peuvent être déclarées au niveau supérieur dans un fichier, localement dans d’autres fonctions, en tant que fonction membre dans une classe ou un objet et en tant que fonction d’extension. Les fonctions d’extension offrent la possibilité, semblable à C#, d’étendre une classe avec de nouvelles fonctionnalités sans avoir à hériter de la classe ou à utiliser un type de modèle de conception tel que Decorator.
Pour les fans de Groovy, Kotlin implémente des constructeurs ; en fait, les constructeurs Kotlin peuvent faire l’objet d’une vérification de type. Kotlin prend en charge les propriétés déléguées, qui peuvent être utilisées pour implémenter des propriétés paresseuses, des propriétés observables, des propriétés vétoables et des propriétés mappées.
De nombreux mécanismes asynchrones disponibles dans d’autres langages peuvent être implémentés sous forme de bibliothèques à l’aide de coroutines Kotlin. Ceci comprend async
/await
à partir de C # et ECMAScript, canaux et sélectionnez à partir de Go, et generators
/yield
de C# et Python.
Programmation fonctionnelle en Kotlin
Autoriser les fonctions de niveau supérieur n’est que le début de l’histoire de la programmation fonctionnelle pour Kotlin. La langue prend également en charge fonctions d’ordre supérieur, fonctions anonymes, lambdas, fonctions en ligne, fermetures, récursivité de queue et génériques. En d’autres termes, Kotlin possède toutes les fonctionnalités et les avantages d’un langage fonctionnel. Par exemple, considérons les fonctions suivantes Idiomes Kotlin.
Filtrer une liste dans Kotlin
val positives = list.filter x -> x > 0
Pour une expression encore plus courte, utilisez it
lorsqu’il n’y a qu’un seul paramètre dans la fonction lambda :
val positives = list.filter it > 0
Parcourir une carte/liste de paires dans Kotlin
for ((k, v) in map) println(“$k -> $v”)
k
et v
peut s’appeler n’importe quoi.
Utiliser des plages dans Kotlin
for (i in 1..100) ... // closed range: includes 100
for (i in 1 until 100) ... // half-open range: does not include 100
for (x in 2..10 step 2) ...
for (x in 10 downTo 1) ...
if (x in 1..10) ...
Les exemples ci-dessus montrent la for
mot-clé ainsi que l’utilisation de plages.
Même si Kotlin est un langage de programmation fonctionnel à part entière, il préserve la majeure partie de la nature orientée objet de Java en tant que style de programmation alternatif, ce qui est très pratique lors de la conversion de code Java existant. Kotlin a Des classes avec des constructeurs, ainsi que des classes internes imbriquées, internes et anonymes, et il a interfaces comme Java 8. Kotlin le fait ne pas avoir un new
mot-clé. Pour créer une instance de classe, appelez le constructeur comme une fonction normale. Nous l’avons vu dans la capture d’écran ci-dessus.
Kotlin a un héritage unique d’une superclasse nommée, et toutes les classes Kotlin ont une superclasse par défaut Any
lequel est ne pas identique à la classe de base Java java.lang.Object
. Any
contient uniquement trois fonctions membres prédéfinies : equals()
, hashCode()
et toString()
.
Les classes Kotlin doivent être marquées avec le open
mot-clé afin de permettre à d’autres classes d’en hériter ; Les classes Java sont un peu à l’opposé, car elles sont héritables sauf si marqué du final
mot-clé. Pour remplacer une méthode de superclasse, la méthode elle-même doit être marquée open
et la méthode de sous-classe doit être marquée override
. Tout cela fait partie de la philosophie de Kotlin qui consiste à rendre les choses explicites plutôt que de s’appuyer sur des valeurs par défaut. Dans ce cas particulier, je peux voir où la manière de Kotlin de marquer explicitement les membres de la classe de base comme ouverts à l’héritage et les membres de la classe dérivée en tant que remplacements évite plusieurs types d’erreurs Java courantes.
Fonctionnalités de sécurité dans Kotlin
En parlant d’éviter les erreurs courantes, Kotlin a été conçu pour éliminer le danger des références de pointeur nul et rationaliser la gestion des valeurs nulles. Il le fait en faisant un null
illégal pour les types standard, en ajoutant des types nullables et en implémentant des notations de raccourci pour gérer les tests pour null.
Par exemple, une variable régulière de type String
ne peut pas tenir null
:
var a: String = "abc"
a = null // compilation error
Si vous devez autoriser les valeurs nulles, par exemple pour conserver les résultats de la requête SQL, vous pouvez déclarer un type nullable en ajoutant un point d’interrogation au type, par exemple String?
.
var b: String? ="abc"
b = null // ok
Les protections vont un peu plus loin. Vous pouvez utiliser un type non nullable en toute impunité, mais vous devez tester un type nullable pour les valeurs null avant de l’utiliser.
Pour éviter la grammaire détaillée normalement nécessaire pour les tests nuls, Kotlin introduit un appel sécuriséécrit ?.
. Par exemple, b?.length
Retour b.length
si b
n’est pas null
et null
Par ailleurs. Le type de cette expression est Int?
.
Autrement dit, b?.length
est un raccourci pour if (b != null) b.length else null
. Cette syntaxe s’enchaîne bien, éliminant beaucoup de logique prolixe, en particulier lorsqu’un objet est rempli à partir d’une série de requêtes de base de données, dont chacune peut échouer. Par exemple, bob?.department?.head?.name
renverrait le nom du chef de service de Bob si Bob, le service et le chef de service sont tous non nuls.
Pour effectuer une certaine opération uniquement pour les valeurs non nulles, vous pouvez utiliser l’opérateur d’appel sécurisé ?.
ensemble avec let
:
val listWithNulls: List<String?> = listOf("A", null)
for (item in listWithNulls)
item?.let println(it) // prints A and ignores null
Souvent, vous souhaitez renvoyer une valeur valide mais spéciale à partir d’une expression nullable, généralement pour pouvoir l’enregistrer dans un type non nullable. Il existe une syntaxe spéciale pour cela appelée l’opérateur Elvis (je ne plaisante pas), écrit ?:
.
val l = b?.length ?: -1
est l’équivalent de
val l: Int = if (b != null) b.length else -1
Dans le même ordre d’idées, Kotlin omet les exceptions vérifiées de Java, qui sont des conditions jetables qui devoir être attrapé. Par exemple, la signature JDK
Appendable append(CharSequence csq) throws IOException;
vous oblige à attraper IOException
chaque fois que vous appelez un append
méthode:
try
log.append(message)
catch (IOException e)
// Do something with the exception
Les concepteurs de Java ont pensé que c’était une bonne idée, et c’était une victoire nette pour les programmes jouets, tant que les programmeurs implémentaient quelque chose de sensé dans le catch
clause. Cependant, trop souvent, dans les gros programmes Java, vous voyez du code dans lequel les éléments obligatoires catch
clause ne contient rien d’autre qu’un commentaire : //todo: handle this
. Cela n’aide personne, et les exceptions vérifiées se sont avérées être une perte nette pour les gros programmes.
Coroutines Kotlin
Coroutines dans Kotlin sont essentiellement des threads légers. Vous les démarrez avec le launch
constructeur de coroutine dans le contexte de certains CoroutineScope
. L’une des étendues de coroutine les plus utiles est runBlocking
qui s’applique à la portée de son bloc de code.
import kotlinx.coroutines.*fun main() = runBlocking // this: CoroutineScope
launch // launch a new coroutine in the scope of runBlocking
delay(1000L) // non-blocking delay for 1 second
println("World!")
println("Hello,")
Ce code produit la sortie suivante, avec un délai d’une seconde entre les lignes :
Hello,
World!
Kotlin pour Android
Jusqu’en mai 2017, les seuls langages de programmation officiellement pris en charge pour Android étaient Java et C++. Google a annoncé le support officiel de Kotlin sur Android à Google I/O 2017, et à partir d’Android Studio 3.0 Kotlin est intégré à l’ensemble d’outils de développement Android. Kotlin peut être ajouté aux versions antérieures d’Android Studio avec un plug-in.
Kotlin se compile avec le même code binaire que Java, interagit avec les classes Java de manière naturelle et partage ses outils avec Java. Comme il n’y a pas de frais généraux pour les appels entre Kotlin et Java, l’ajout progressif de Kotlin à une application Android actuellement en Java est parfaitement logique. Les quelques cas où l’interopérabilité entre Kotlin et le code Java manquent de grâce, tels que les propriétés d’ensemble Java uniquement, sont rarement rencontrés et facilement résolus.
Pinterest était l’enfant d’affiche pour les applications Android écrites en Kotlin dès novembre 2016, et il a été mentionné en bonne place lors de Google I/O 2017 dans le cadre de l’annonce de Kotlin. De plus, l’équipe Kotlin aime citer les applications Evernote, Trello, Gradle, Corda, Spring et Coursera pour Android.
Kotlin contre Java
La question de savoir s’il faut choisir Kotlin ou Java pour un nouveau développement a beaucoup été soulevée dans la communauté Android depuis l’annonce de Google I/O, bien que les gens posaient déjà la question en février 2016 lors de la livraison de Kotlin 1.0. La réponse courte est que le code Kotlin est plus sûr et plus concis que le code Java, et que les fichiers Kotlin et Java peuvent coexister dans les applications Android, de sorte que Kotlin est non seulement utile pour les nouvelles applications, mais également pour étendre les applications Java existantes.
Le seul argument convaincant que j’ai vu pour choisir Java plutôt que Kotlin serait pour le cas des débutants complets en développement Android. Pour eux, il pourrait y avoir un obstacle à surmonter étant donné que, historiquement, la plupart de la documentation et des exemples Android sont en Java. D’autre part, la conversion de Java en Kotlin dans Android Studio consiste simplement à coller le code Java dans un fichier Kotlin. En 2022, six ans après Kotlin 1.0, je ne suis pas sûr que cette barrière de documentation ou d’exemple existe toujours de manière significative.
Pour presque tous ceux qui font du développement Android, les avantages de Kotlin sont convaincants. Le temps typique indiqué pour qu’un développeur Java apprenne Kotlin est de quelques heures – un petit prix à payer pour éliminer les erreurs de référence nulles, activer les fonctions d’extension, prendre en charge la programmation fonctionnelle et ajouter des coroutines. L’estimation approximative typique indique une réduction d’environ 40 % du nombre de lignes de code de Java à Kotlin.
Kotlin contre Scala
La question de savoir s’il faut choisir Kotlin ou Scala ne revient pas souvent dans la communauté Android. Si vous regardez GitHub (à partir d’octobre 2022) et rechercher des référentiels Androidvous en trouverez environ 50 000 qui utilisent Java, 24 000 qui utilisent Kotlin et (ahem) 73 qui utilisent Scala. Oui, il est possible de écrire des applications Android en Scalamais peu de développeurs s’en soucient.
Dans d’autres environnements, la situation est différente. Par exemple, Apache Spark est principalement écrit en Scala, et les applications Big Data pour Spark sont souvent écrites en Scala.
À bien des égards, Scala et Kotlin représentent la fusion de la programmation orientée objet, illustrée par Java, avec la programmation fonctionnelle. Les deux langages partagent de nombreux concepts et notations, tels que des déclarations immuables utilisant val
et les déclarations mutables utilisant var
, mais diffèrent légèrement sur d’autres, comme l’endroit où placer la flèche lors de la déclaration d’une fonction lambda, et s’il faut utiliser une flèche simple ou une flèche double. Le Kotlin data class
cartes de la Scala case class
.
Kotlin définit les variables nullables d’une manière similaire à Groovy, C# et F# ; la plupart des gens l’obtiennent rapidement. Scala, d’autre part, définit des variables nullables à l’aide de la Option
monade, ce qui peut être si rébarbatif que certains auteurs semblent penser que Scala n’a pas de sécurité nulle.
Un déficit clair de Scala est que ses temps de compilation ont tendance à être longs, ce qui est le plus évident lorsque vous construisez un grand corps de Scala, tel que le référentiel Spark, à partir de la source. Kotlin, d’autre part, a été conçu pour se compiler rapidement dans les scénarios de développement de logiciels les plus fréquents, et se compile en fait souvent plus rapidement que le code Java.
Interopérabilité de Kotlin avec Java
À ce stade, vous vous demandez peut-être comment Kotlin gère les résultats des appels d’interopérabilité Java, compte tenu des différences de null
gestion et vérification des exceptions. Kotlin déduit silencieusement et de manière fiable ce qu’on appelle un “type de plate-forme” qui se comporte exactement comme un type Java, ce qui signifie qu’il est nullable mais peut générer des exceptions de pointeur nul. Kotlin peut également injecter une assertion dans le code au moment de la compilation pour éviter de déclencher une véritable exception de pointeur nul. Il n’y a pas de notation de langage explicite pour un type de plate-forme, mais dans le cas où Kotlin doit signaler un type de plate-forme, comme dans un message d’erreur, il ajoute !
au genre.