• 12 heures
  • Facile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 01/08/2024

Découvrez les extensions

Comme nous avons pu le voir dans le premier chapitre de ce cours, une des principales préoccupations de Kotlin est de pouvoir s’intégrer le plus facilement et proprement possible à du code existant écrit en Java.

D’ailleurs, même les programmes écrits uniquement en Kotlin utilisent TOUJOURS des librairies ou frameworks écrits en Java, comme le JDK ou le framework Android, par exemple. Les développeurs JetBrains, aussi performants soient-ils, ne pouvaient pas réécrire tous ces frameworks en Kotlin ! :D #FautPasPousserMéméDansLesOrties

Ainsi, il a fallu trouver une approche logicielle pour "étendre" les fonctionnalités de ces librairies ou frameworks Java actuels : les "extensions" en Kotlin ont alors été créées afin de répondre à ce besoin.

L’extension grâce aux fonctions

Afin d’étendre le comportement d’une classe, qu’elle soit écrite en Java ou en Kotlin, nous allons pouvoir, grâce au mécanisme d’extension que nous offre Kotlin, ajouter des fonctions qui seront perçues comme "appartenant" à la classe elle-même.

Par exemple, imaginons que nous souhaitions faire en sorte d'ajouter une méthode  sayHello()  à toutes les variables de type  String  . Comment allons-nous nous y prendre ?

Eh bien nous créons une classe  MyString  (héritant de  String  ) et ajoutons à celle-ci la méthode  sayHello()  ? :honte:

Eh non ! Cette approche est Java-Friendly : en suivant votre approche, nous serions obligés d’utiliser la classe  MyString  contenant notre nouvelle méthode pour gérer tous nos  String  . C’est un peu contraignant, vous ne trouvez pas ?

Oui, c’est vrai…:euh:

Eh puis de toute manière, la classe String est  final , nous ne pouvons donc pas hériter d'elle ! :p

Cependant, grâce aux extensions en Kotlin, nous allons pouvoir "ajouter" la méthode  sayHello()  à l’intérieur de la classe  String , sans modifier directement cette dernière (car, de toute manière, on ne pourrait pas, vu qu’elle se trouve dans le JDK ;) ) !

Référence : Star wars
Référence : Star Wars

Eh si ! C’est d’ailleurs tout le pouvoir et l’intérêt des extensions... ;) Celles-ci vont d’ailleurs se comporter comme nos fameuses "top-level functions".

Ainsi, créons notre première extension, et ajoutons la fonction  sayHello()  à la classe  String   :

Créez une extension en Kotlin
Créez une extension en Kotlin

Une extension se déclare dans un fichier à part (1), que l’on nomme généralement d’après le nom de la classe que l’on souhaite étendre, suivi du mot "Extensions" ou "Ext". Dans l’absolu, cela n’a aucune importance (vous pourriez appeler le fichier "test", le résultat serait le même), mais cette approche permet tout de même d’améliorer la lisibilité et la compréhension de notre projet. :)

Puis, à l’intérieur de ce fichier, nous créons une "fonction d’extension" (2) qui permettra en quelque sorte "d’ajouter une méthode" dans la classe  String  :

fun String sayHello() = print("This variable contains: $this")

Afin de déclarer une fonction d’extension, nous commençons comme d’habitude par le mot-clé  fun . Nous indiquons ensuite le nom de la classe que nous souhaitons étendre (  String  ), que l’on appelle aussi le "type récepteur" (ou "Receiver Type", en anglais), suivi d’un point  .  et du nom de la méthode que nous souhaitons créer (  sayHello  ).

Nous renseignons à la suite le contenu de notre méthode (ici, un simple  print  ), et nous récupérons l’instance de l’objet utilisée dans cette extension grâce au mot-clé  this  .

Pour terminer, nous appelons cette fonction (3) sur une variable de type  String  . On remarque qu’un import vers cette extension a dû être réalisé afin d’indiquer au compilateur où la récupérer.

Ainsi, l’extension  sayHello  sera résolue statiquement par le compilateur. Derrière toute cette "magie" se cache en réalité quelque chose d’assez simple : la méthode  sayHello  est une méthode statique publique acceptant en unique paramètre un objet de type  String  . ;)

D’ailleurs, pour vous le prouver, appelons cette méthode depuis une classe Java :

Appeler une extension Kotlin en Java
Appeler une extension Kotlin en Java

Cela ne vous rappelle-t-il pas quelque chose ? :) C’est exactement le même principe que les "top-level functions" vues dans le précédent chapitre. Pour chaque fonction d’extension créée, le compilateur Kotlin créera l’équivalent en Java sous la forme d’une classe contenant des méthodes publiques statiques. Bien pensé, n'est-ce pas ?

Les fonctions d’extension peuvent accéder aux propriétés et méthodes de la classe qu’elles "étendent", comme si elles étaient placées à l’intérieur de celle-ci. En revanche, l’extension en Kotlin ne vous permettra pas de passer outre l’encapsulation de la classe ! Vous ne pourrez donc pas accéder aux méthodes ou aux propriétés définies comme  private ,  internal  (hors du module) ou  protected  .

Visibilité d'une fonction d'extension
Encapsulation d'une fonction d'extension

Sachez également qu’une extension ne pourra pas être surchargée : impossible donc d’utiliser le mot-clé  override  pour modifier le comportement d’une extension déjà créée.

L’extension grâce aux propriétés

La fonctionnalité d’extension de Kotlin ne se limite pas qu’aux fonctions ! :) Vous pouvez aussi créer des "propriétés d’extension".

Attention, cependant, il faut bien que vous compreniez que cette propriété ne se trouvera pas à l’intérieur de la classe étendue, et ne pourra donc pas "stocker" de valeur en soi dans une instance (objet) de la classe.

Voyez plutôt les propriétés d’extension comme un moyen de récupérer OU/ET modifier un élément de la classe que vous souhaitez étendre, en une seule déclaration. D’ailleurs, une propriété d’extension pourra très bien être remplacée par deux fonctions d’extension (une fonction pour la récupération et une autre fonction pour la modification).

Propriété d'extension en Kotlin
Propriété d'extension en Kotlin

Dans cet exemple, nous avons créé une propriété d’extension à la classe  StringBuilder  , que nous avons appelée firstLetter  . Le but de celle-ci est de récupérer ET de modifier la première lettre d’une String  créée via la classe  StringBuilder  .

Nous utilisons pour cela les mots-clés  get  et  set  , de la même manière que nous avons pu le faire dans un précédent chapitre.

Sachez cependant que les propriétés d’extension n’ont pas de "Backing Field" : vous ne pourrez donc pas utiliser le mot-clé  field  dans leur getter et/ou leur setter ! (Et cela est normal, car la propriété n’existe en réalité pas dans la classe étendue.)

D’accord ! Mais est-ce que je pourrai les utiliser également en Java ?

Bien sûr ! Tout comme les fonctions d’extension, les propriétés d’extension ne sont en réalité que des méthodes statiques publiques que nous pourrons également appeler en Java de cette manière :

Propriété d'extension appelée en Java
Propriété d'extension appelée en Java

Le compilateur Kotlin génère donc automatiquement deux méthodes statiques (un getter et un setter) pour la propriété d’extension que nous venons de créer. Plutôt pratique, non ? :)

Practice Makes Perfect!

La théorie, c'est bien, mais la pratique, c'est encore mieux ! Justement, nous vous avons concocté un petit exercice interactif de fin de chapitre pour appliquer toutes ces nouvelles connaissances.

En résumé

  • En Kotlin, les extensions permettent d’ajouter des fonctions ou des propriétés à une classe, qui seront perçues comme "appartenant" à la classe elle-même.

  • Une extension se crée dans un fichier à part, sans toucher au code source de la classe à étendre.

Pour aller plus loin

Exemple de certificat de réussite
Exemple de certificat de réussite