Dix fonctionnalités Kotlin pour booster le développement d'Android
Publié: 2022-03-11introduction
Il y a quelque temps, Tomasz a présenté le développement de Kotlin sur Android. Pour rappel : Kotlin est un nouveau langage de programmation développé par Jetbrains, la société à l'origine de l'un des IDE Java les plus populaires, IntelliJ IDEA. Comme Java, Kotlin est un langage polyvalent. Puisqu'il est conforme au bytecode Java Virtual Machine (JVM), il peut être utilisé côte à côte avec Java, et il n'entraîne pas de surcharge de performances.
Dans cet article, je couvrirai le top 10 des fonctionnalités utiles pour booster votre développement Android.
Note : au moment de la rédaction de cet article, les versions actuelles étaient Android Studio 2.1.1. et Kotlin 1.0.2.
Configuration Kotlin
Étant donné que Kotlin est développé par JetBrains, il est bien pris en charge dans Android Studio et IntelliJ.
La première étape consiste à installer le plugin Kotlin. Après avoir réussi, de nouvelles actions seront disponibles pour convertir votre Java en Kotlin. Deux nouvelles options sont :
- Créez un nouveau projet Android et configurez Kotlin dans le projet.
- Ajoutez la prise en charge de Kotlin à un projet Android existant.
Pour savoir comment créer un nouveau projet Android, consultez le guide officiel étape par étape. Pour ajouter la prise en charge de Kotlin à un projet nouvellement créé ou existant, ouvrez la boîte de dialogue d'action de recherche à l'aide Command + Shift + A
sur Mac ou Ctrl + Shift + A
sur Windows/Linux, et appelez l'action Configure Kotlin in Project
.
Pour créer une nouvelle classe Kotlin, sélectionnez :
-
File
>New
>Kotlin file/class
, ou -
File
>New
>Kotlin activity
Alternativement, vous pouvez créer une classe Java et la convertir en Kotlin en utilisant l'action mentionnée ci-dessus. N'oubliez pas que vous pouvez l'utiliser pour convertir n'importe quelle classe, interface, énumération ou annotation, et cela peut être utilisé pour comparer facilement Java au code Kotlin.
Un autre élément utile qui permet d'économiser beaucoup de frappe sont les extensions Kotlin. Pour les utiliser, vous devez appliquer un autre plugin dans votre fichier build.gradle
de module :
apply plugin: 'kotlin-android-extensions'
Mise en garde : si vous utilisez l'action du plug-in Kotlin pour configurer votre projet, il placera le code suivant dans votre fichier build.gradle
de niveau supérieur :
buildscript { ext.kotlin_version = '1.0.2' repositories { jcenter() } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } }
Cela empêchera l'extension de fonctionner. Pour résoudre ce problème, copiez simplement ce code dans chacun des modules du projet dans lesquels vous souhaitez utiliser Kotlin.
Si vous configurez tout correctement, vous devriez pouvoir exécuter et tester votre application de la même manière que vous le feriez dans un projet Android standard, mais en utilisant maintenant Kotlin.
Gagner du temps avec Kotlin
Commençons donc par décrire certains aspects clés du langage Kotlin et par fournir des conseils sur la façon dont vous pouvez gagner du temps en l'utilisant à la place de Java.
Fonctionnalité #1 : Importation de mise en page statique
L'un des codes passe-partout les plus courants dans Android utilise la fonction findViewById()
pour obtenir des références à vos vues dans les activités ou les fragments.
Il existe des solutions, telles que la bibliothèque Butterknife, qui permettent d'économiser un peu de frappe, mais Kotlin franchit une autre étape en vous permettant d'importer toutes les références aux vues de la mise en page avec une seule importation.
Par exemple, considérez la disposition XML d'activité suivante :
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:andro xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="co.ikust.kotlintest.MainActivity"> <TextView android: android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout>
Et le code d'activité qui l'accompagne :
package co.ikust.kotlintest import android.support.v7.app.AppCompatActivity import android.os.Bundle import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) helloWorldTextView.text = "Hello World!" } }
Pour obtenir les références de toutes les vues de la mise en page avec un ID défini, utilisez l'extension Android Kotlin Anko. N'oubliez pas de saisir cette déclaration d'importation :
import kotlinx.android.synthetic.main.activity_main.*
Notez que vous n'avez pas besoin d'écrire des points-virgules à la fin des lignes dans Kotlin car ils sont facultatifs.
Le TextView
de la mise en page est importé en tant qu'instance de TextView
avec le nom égal à l'ID de la vue. Ne soyez pas confus par la syntaxe, qui est utilisée pour définir l'étiquette :
helloWorldTextView.text = "Hello World!"
Nous couvrirons cela sous peu.
Mises en garde :
- Assurez-vous d'importer la mise en page correcte, sinon les références de vue importées auront une valeur
null
. - Lorsque vous utilisez des fragments, assurez-vous que les références de vue importées sont utilisées après l'appel de la fonction
onCreateView()
. Importez la mise en page dans la fonctiononCreateView()
et utilisez les références de vue pour configurer l'interface utilisateur dansonViewCreated()
. Les références ne seront pas affectées avant la fin de la méthodeonCreateView()
.
Fonctionnalité n° 2 : écriture de classes POJO avec Kotlin
Quelque chose qui fera gagner le plus de temps avec Kotlin est d'écrire les classes POJO (Plain Old Java Object) utilisées pour contenir les données. Par exemple, dans le corps de la requête et de la réponse d'une API RESTful. Dans les applications qui reposent sur l'API RESTful, il y aura de nombreuses classes comme celle-là.
Dans Kotlin, beaucoup est fait pour vous et la syntaxe est concise. Par exemple, considérez la classe suivante en Java :
public class User { private String firstName; private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } }
Lorsque vous travaillez avec Kotlin, vous n'avez plus besoin d'écrire un mot clé public. Par défaut, tout est de portée publique. Par exemple, si vous voulez déclarer une classe, écrivez simplement :
class MyClass { }
L'équivalent du code Java ci-dessus en Kotlin :
class User { var firstName: String? = null var lastName: String? = null }
Eh bien, cela économise beaucoup de frappe, n'est-ce pas? Passons en revue le code Kotlin.
Lors de la définition de variables dans Kotlin, il existe deux options :
- Variables mutables, définies par le mot-clé
var
. - Variables immuables, définies par le mot-clé
val
.
La prochaine chose à noter est que la syntaxe diffère un peu de Java ; d'abord, vous déclarez le nom de la variable, puis suivez avec le type. De plus, par défaut, les propriétés sont des types non nuls, ce qui signifie qu'elles ne peuvent pas accepter de valeur null
. Pour définir une variable pour accepter une valeur null
, un point d'interrogation doit être ajouté après le type. Nous en parlerons plus tard et de la sécurité nulle dans Kotlin.
Une autre chose importante à noter est que Kotlin n'a pas la possibilité de déclarer des champs pour la classe ; seules les propriétés peuvent être définies. Ainsi, dans ce cas, firstName
et lastName
sont des propriétés auxquelles ont été attribuées des méthodes getter/setter par défaut. Comme mentionné, dans Kotlin, ils sont tous deux publics par défaut.
Les accesseurs personnalisés peuvent être écrits, par exemple :
class User { var firstName: String? = null var lastName: String? = null val fullName: String? get() firstName + " " + lastName }
De l'extérieur, en ce qui concerne la syntaxe, les propriétés se comportent comme des champs publics en Java :
val userName = user.firstName user.firstName = "John"
Notez que la nouvelle propriété fullName
est en lecture seule (définie par le mot-clé val
) et a un getter personnalisé ; il ajoute simplement le nom et le prénom.
Toutes les propriétés de Kotlin doivent être attribuées lorsqu'elles sont déclarées ou se trouvent dans un constructeur. Il y a des cas où ce n'est pas pratique; par exemple, pour les propriétés qui seront initialisées via l'injection de dépendances. Dans ce cas, un modificateur lateinit
peut être utilisé. Voici un exemple:
class MyClass { lateinit var firstName : String; fun inject() { firstName = "John"; } }
Plus de détails sur les propriétés peuvent être trouvés dans la documentation officielle.
Fonctionnalité #3 : Héritage de classe et constructeurs
Kotlin a également une syntaxe plus concise en ce qui concerne les constructeurs.
Constructeurs
Les classes Kotlin ont un constructeur principal et un ou plusieurs constructeurs secondaires. Un exemple de définition d'un constructeur principal :
class User constructor(firstName: String, lastName: String) { }
Le constructeur principal se place après le nom de la classe dans la définition de la classe. Si le constructeur principal n'a pas d'annotations ou de modificateurs de visibilité, le mot-clé constructor peut être omis :
class Person(firstName: String) { }
Notez qu'un constructeur principal ne peut pas avoir de code ; toute initialisation doit être effectuée dans le bloc de code init
:
class Person(firstName: String) { init { //perform primary constructor initialization here } }
De plus, un constructeur principal peut être utilisé pour définir et initialiser des propriétés :
class User(var firstName: String, var lastName: String) { // ... }
Tout comme les propriétés normales, les propriétés définies à partir d'un constructeur principal peuvent être immuables ( val
) ou mutables ( var
).
Les classes peuvent également avoir des constructeurs secondaires ; la syntaxe pour en définir un est la suivante :
class User(var firstName: String, var lastName) { constructor(name: String, parent: Person) : this(name) { parent.children.add(this) } }
Notez que chaque constructeur secondaire doit déléguer à un constructeur principal. Ceci est similaire à Java, qui utilise this
mot-clé :
class User(val firstName: String, val lastName: String) { constructor(firstName: String) : this(firstName, "") { //... } }
Lors de l'instanciation de classes, notez que Kotlin n'a pas de new
mots-clés, tout comme Java. Pour instancier la classe User
susmentionnée, utilisez :
val user = User("John", "Doe)
Présentation de l'héritage
Dans Kotlin, toutes les classes s'étendent de Any
, qui est similaire à Object
en Java. Par défaut, les classes sont fermées, comme les classes finales en Java. Ainsi, pour étendre une classe, il faut la déclarer open
ou abstract
:
open class User(val firstName, val lastName) class Administrator(val firstName, val lastName) : User(firstName, lastName)
Notez que vous devez déléguer au constructeur par défaut de la classe étendue, ce qui revient à appeler la méthode super()
dans le constructeur d'une nouvelle classe en Java.
Pour plus de détails sur les classes, consultez la documentation officielle.
Fonctionnalité n° 4 : Expressions lambda
Les expressions Lambda, introduites avec Java 8, sont l'une de ses fonctionnalités préférées. Cependant, les choses ne sont pas si brillantes sur Android, car il ne prend toujours en charge que Java 7 et il semble que Java 8 ne sera pas pris en charge de si tôt. Ainsi, des solutions de contournement, telles que Retrolambda, apportent des expressions lambda à Android.
Avec Kotlin, aucune bibliothèque ou solution de contournement supplémentaire n'est requise.
Fonctions dans Kotlin
Commençons par passer rapidement en revue la syntaxe de la fonction dans Kotlin :
fun add(x: Int, y: Int) : Int { return x + y }
La valeur de retour de la fonction peut être omise, et dans ce cas, la fonction retournera Int
. Il vaut la peine de répéter que tout dans Kotlin est un objet, étendu à partir de Any
, et qu'il n'y a pas de types primitifs.
Un argument de la fonction peut avoir une valeur par défaut, par exemple :
fun add(x: Int, y: Int = 1) : Int { return x + y; }
Dans ce cas, la fonction add()
peut être invoquée en passant uniquement l'argument x
. Le code Java équivalent serait :
int add(int x) { Return add(x, 1); } int add(int x, int y) { return x + y; }
Une autre bonne chose lors de l'appel d'une fonction est que des arguments nommés peuvent être utilisés. Par exemple:
add(y = 12, x = 5)
Pour plus de détails sur les fonctions, consultez la documentation officielle.
Utilisation des expressions Lambda dans Kotlin
Les expressions lambda dans Kotlin peuvent être considérées comme des fonctions anonymes dans Java, mais avec une syntaxe plus concise. À titre d'exemple, montrons comment implémenter l'écouteur de clic en Java et Kotlin.
En Java :
view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(v.getContext(), "Clicked on view", Toast.LENGTH_SHORT).show(); } };
Dans Kotlin :
view.setOnClickListener({ view -> toast("Click") })
Wow! Une seule ligne de code ! Nous pouvons voir que l'expression lambda est entourée d'accolades. Les paramètres sont déclarés en premier, et le corps va après le signe ->
. Avec l'écouteur de clic, le type du paramètre de vue n'est pas spécifié car il peut être déduit. Le corps est simplement un appel à la fonction toast()
pour afficher le toast, fourni par Kotlin.
De plus, si les paramètres ne sont pas utilisés, nous pouvons les laisser de côté :
view.setOnClickListener({ toast("Click") })
Kotlin a optimisé les bibliothèques Java, et toute fonction qui reçoit une interface avec une méthode pour un argument peut être appelée avec un argument de fonction (au lieu d'Interface).

De plus, si la fonction est le dernier paramètre, elle peut être déplacée hors des parenthèses :
view.setOnClickListener() { toast("Click") }
Enfin, si la fonction n'a qu'un seul paramètre qui est une fonction, les parenthèses peuvent être omises :
view.setOnClickListener { toast("Click") }
Pour plus d'informations, consultez le livre Kotlin pour les développeurs Android d'Antonio Leiva et la documentation officielle.
Fonctions d'extension
Kotlin, similaire à C #, offre la possibilité d'étendre les classes existantes avec de nouvelles fonctionnalités en utilisant des fonctions d'extension. Par exemple, une méthode d'extension qui calculerait le hachage MD5 d'un String
:
fun String.md5(): ByteArray { val digester = MessageDigest.getInstance("MD5") digester.update(this.toByteArray(Charset.defaultCharset())) return digester.digest() }
Notez que le nom de la fonction est précédé du nom de la classe étendue (dans ce cas, String
), et que l'instance de la classe étendue est disponible via this
mot clé.
Les fonctions d'extension sont l'équivalent des fonctions utilitaires Java. L'exemple de fonction en Java ressemblerait à :
public static int toNumber(String instance) { return Integer.valueOf(instance); }
L'exemple de fonction doit être placé dans une classe Utility. Cela signifie que les fonctions d'extension ne modifient pas la classe étendue d'origine, mais constituent un moyen pratique d'écrire des méthodes utilitaires.
Caractéristique n°5 : Sécurité nulle
L'une des choses que vous bousculez le plus en Java est probablement NullPointerException
. La sécurité nulle est une fonctionnalité qui a été intégrée au langage Kotlin et qui est si implicite que vous n'aurez généralement pas à vous en soucier. La documentation officielle indique que les seules causes possibles de NullPointerExceptions
sont :
- Un appel explicite pour
NullPointerException
. - Utiliser le
!!
opérateur (que j'expliquerai plus tard). - Code Java externe.
- Si la propriété
lateinit
est accessible dans le constructeur avant son initialisation, uneUninitializedPropertyAccessException
sera levée.
Par défaut, toutes les variables et propriétés de Kotlin sont considérées comme non-null
(incapables de contenir une valeur null
) si elles ne sont pas explicitement déclarées comme nullables. Comme déjà mentionné, pour définir une variable pour accepter une valeur null
, un point d'interrogation doit être ajouté après le type. Par exemple:
val number: Int? = null
Cependant, notez que le code suivant ne compilera pas :
val number: Int? = null number.toString()
Cela est dû au fait que le compilateur effectue des vérifications null
. Pour compiler, une vérification null
doit être ajoutée :
val number: Int? = null if(number != null) { number.toString(); }
Ce code se compilera avec succès. Ce que fait Kotlin en arrière-plan, dans ce cas, c'est que ce number
devient nun-null
( Int
au lieu de Int?
) à l'intérieur du bloc if.
La vérification null
peut être simplifiée à l'aide de l'opérateur d'appel sécurisé ( ?.
):
val number: Int? = null number?.toString()
La deuxième ligne ne sera exécutée que si le nombre n'est pas null
. Vous pouvez même utiliser le célèbre opérateur Elvis ( ?:
):
val number Int? = null val stringNumber = number?.toString() ?: "Number is null"
Si l'expression à gauche de ?:
n'est pas null
, elle est évaluée et renvoyée. Sinon, le résultat de l'expression de droite est renvoyé. Une autre chose intéressante est que vous pouvez utiliser throw
ou return
sur le côté droit de l'opérateur Elvis car ce sont des expressions dans Kotlin. Par exemple:
fun sendMailToUser(user: User) { val email = user?.email ?: throw new IllegalArgumentException("User email is null") //... }
Le !! Opérateur
Si vous voulez qu'une NullPointerException
soit lancée de la même manière qu'en Java, vous pouvez le faire avec le !!
opérateur. Le code suivant lèvera une NullPointerException
:
val number: Int? = null number!!.toString()
Fonderie
Casting done en utilisant un mot-clé as
:
val x: String = y as String
Ceci est considéré comme un casting "non sécurisé", car il ClassCastException
si le cast n'est pas possible, comme le fait Java. Il existe un opérateur de cast "Sûr" qui renvoie la valeur null
au lieu de lever une exception :
val x: String = y as? String
Pour plus de détails sur le casting, consultez la section Type Casts and Casts de la documentation officielle, et pour plus de détails sur la sécurité null
, consultez la section Null-Safety.
propriétés lateinit
Il existe un cas dans lequel l'utilisation des propriétés lateinit
peut provoquer une exception similaire à NullPointerException
. Considérez la classe suivante :
class InitTest { lateinit var s: String; init { val len = this.s.length } }
Ce code sera compilé sans avertissement. Cependant, dès qu'une instance de TestClass
est créée, une UninitializedPropertyAccessException
sera levée car la propriété s
est accessible avant son initialisation.
Fonctionnalité #6 : Fonction with()
La fonction with()
est utile et est fournie avec la bibliothèque standard Kotlin. Il peut être utilisé pour économiser un peu de frappe si vous avez besoin d'accéder à de nombreuses propriétés d'un objet. Par exemple:
with(helloWorldTextView) { text = "Hello World!" visibility = View.VISIBLE }
Il reçoit un objet et une fonction d'extension en paramètres. Le bloc de code (entre accolades) est une expression lambda pour la fonction d'extension de l'objet spécifié comme premier paramètre.
Fonctionnalité n° 7 : surcharge de l'opérateur
Avec Kotlin, des implémentations personnalisées peuvent être fournies pour un ensemble prédéfini d'opérateurs. Pour implémenter un opérateur, une fonction membre ou une fonction d'extension avec le nom donné doit être fournie.
Par exemple, pour implémenter l'opérateur de multiplication, une fonction membre ou une fonction d'extension, avec le nom times(argument)
, doit être fournie :
operator fun String.times(b: Int): String { val buffer = StringBuffer() for (i in 1..b) { buffer.append(this) } return buffer.toString() }
L'exemple ci-dessus montre une implémentation de l'opérateur binaire *
sur le String
. Par exemple, l'expression suivante attribuera la valeur "TestTestTestTest" à une variable newString
:
val newString = "Test" * 4
Comme les fonctions d'extension peuvent être utilisées, cela signifie que le comportement par défaut des opérateurs pour tous les objets peut être modifié. C'est une épée à double tranchant et doit être utilisée avec prudence. Pour une liste des noms de fonction pour tous les opérateurs qui peuvent être surchargés, consultez la documentation officielle.
Une autre grande différence par rapport à Java sont les opérateurs ==
et !=
. L'opérateur ==
se traduit par :
a?.equals(b) ?: b === null
Tandis que l'opérateur !=
se traduit par :
!(a?.equals(b) ?:
Cela signifie que l'utilisation de ==
n'effectue pas de vérification d'identité comme en Java (comparez si les instances d'un objet sont identiques), mais se comporte de la même manière que la méthode equals()
avec les vérifications null
.
Pour effectuer un contrôle d'identité, les opérateurs ===
et !==
doivent être utilisés dans Kotlin.
Fonctionnalité #8 : Propriétés déléguées
Certaines propriétés partagent des comportements communs. Par exemple:
- Propriétés à initialisation différée qui sont initialisées lors du premier accès.
- Propriétés qui implémentent Observable dans le modèle Observer.
- Les propriétés qui sont stockées dans une carte à la place en tant que champs séparés.
Pour faciliter la mise en œuvre de cas comme celui-ci, Kotlin prend en charge les propriétés déléguées :
class SomeClass { var p: String by Delegate() }
Cela signifie que les fonctions getter et setter pour la propriété p
sont gérées par une instance d'une autre classe, Delegate
.
Un exemple de délégué pour la propriété String
:
class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value has been assigned to '${property.name} in $thisRef.'") } }
L'exemple ci-dessus imprime un message lorsqu'une propriété est attribuée ou lue.
Des délégués peuvent être créés pour les propriétés modifiables ( var
) et en lecture seule ( val
).
Pour une propriété en lecture seule, la méthode getValue
doit être implémentée. Il prend deux paramètres (tirés de la documentation officielle) :
- récepteur - doit être le même ou un super-type du propriétaire (pour les propriétés d'extension, il s'agit du type en cours d'extension).
- metadata - doit être de type
KProperty<*>
ou son supertype.
Cette fonction doit retourner le même type que la propriété, ou son sous-type.
Pour une propriété mutable, un délégué doit fournir en plus une fonction nommée setValue
qui prend les paramètres suivants :
- récepteur - identique à
getValue()
. - metadata - identique à
getValue()
. - nouvelle valeur - doit être du même type qu'une propriété ou son supertype.
Il existe quelques délégués standard fournis avec Kotlin qui couvrent les situations les plus courantes :
- Fainéant
- Observable
- Droit de veto
Fainéant
Lazy est un délégué standard qui prend une expression lambda comme paramètre. L'expression lambda transmise est exécutée la première fois que la méthode getValue()
est appelée.
Par défaut, l'évaluation des propriétés paresseuses est synchronisée. Si vous n'êtes pas concerné par le multi-threading, vous pouvez utiliser lazy(LazyThreadSafetyMode.NONE) { … }
pour obtenir des performances supplémentaires.
Observable
Le Delegates.observable()
est destiné aux propriétés qui doivent se comporter comme des Observables dans le modèle Observer. Il accepte deux paramètres, la valeur initiale et une fonction qui a trois arguments (propriété, ancienne valeur et nouvelle valeur).
L'expression lambda donnée sera exécutée chaque fois que la méthode setValue()
sera appelée :
class User { var email: String by Delegates.observable("") { prop, old, new -> //handle the change from old to new value } }
Droit de veto
Ce délégué standard est un type spécial d'Observable qui vous permet de décider si une nouvelle valeur affectée à une propriété sera stockée ou non. Il peut être utilisé pour vérifier certaines conditions avant d'attribuer une valeur. Comme avec Delegates.observable()
, il accepte deux paramètres : la valeur initiale et une fonction.
La différence est que la fonction renvoie une valeur booléenne. S'il renvoie true
, la nouvelle valeur affectée à la propriété sera stockée ou sinon supprimée.
var positiveNumber = Delegates.vetoable(0) { d, old, new -> new >= 0 }
L'exemple donné ne stockera que les nombres positifs affectés à la propriété.
Pour plus de détails, consultez la documentation officielle.
Fonctionnalité n° 9 : Mapper un objet sur une carte
Un cas d'utilisation courant consiste à stocker les valeurs des propriétés dans une carte. Cela se produit souvent dans les applications qui fonctionnent avec des API RESTful et analysent des objets JSON. Dans ce cas, une instance de carte peut être utilisée comme délégué pour une propriété déléguée. Un exemple tiré de la documentation officielle :
class User(val map: Map<String, Any?>) { val name: String by map val age: Int by map }
Dans cet exemple, User
a un constructeur principal qui prend une carte. Les deux propriétés prendront les valeurs de la carte qui sont mappées sous des clés égales aux noms de propriété :
val user = User(mapOf( "name" to "John Doe", "age" to 25 ))
La propriété name de la nouvelle instance d'utilisateur se verra attribuer la valeur "John Doe" et la propriété age la valeur 25.
Cela fonctionne également pour les propriétés var en combinaison avec MutableMap
:
class MutableUser(val map: MutableMap<String, Any?>) { var name: String by map var age: Int by map }
Fonctionnalité #10 : Collections et opérations fonctionnelles
Avec la prise en charge des lambdas dans Kotlin, les collections peuvent être exploitées à un nouveau niveau.
Tout d'abord, Kotlin fait la distinction entre les collections mutables et immuables. Par exemple, il existe deux versions de l'interface Iterable :
- Itérable
- MutableIterable
Il en va de même pour les interfaces Collection , List , Set et Map .
Par exemple, cette opération any
renvoie true
si au moins un élément correspond au prédicat donné :
val list = listOf(1, 2, 3, 4, 5, 6) assertTrue(list.any { it % 2 == 0 })
Pour une liste complète des opérations fonctionnelles pouvant être effectuées sur les collections, consultez cet article de blog.
Conclusion
Nous venons de gratter la surface de ce que propose Kotlin. Pour ceux qui souhaitent en savoir plus et en savoir plus, consultez:
- Articles et livre du blog Kotlin d'Antonio Leiva.
- Documentation officielle et tutoriels de JetBrains.
En résumé, Kotlin vous offre la possibilité de gagner du temps lors de l'écriture d'applications Android natives en utilisant une syntaxe intuitive et concise. C'est encore un langage de programmation jeune, mais à mon avis, il est maintenant suffisamment stable pour être utilisé pour créer des applications de production.
Les avantages d'utiliser Kotlin :
- Le support par Android Studio est transparent et excellent.
- Il est facile de convertir un projet Java existant en Kotlin.
- Le code Java et Kotlin peuvent coexister dans le même projet.
- Il n'y a pas de surcharge de vitesse dans l'application.
Les inconvénients :
- Kotlin ajoutera ses bibliothèques au
.apk
généré, de sorte que la taille finale du.apk
sera supérieure d'environ 300 Ko. - En cas d'abus, la surcharge de l'opérateur peut conduire à un code illisible.
- L'IDE et la saisie semi-automatique se comportent un peu plus lentement lorsque vous travaillez avec Kotlin qu'avec les projets Java Android purs.
- Les temps de compilation peuvent être un peu plus longs.