Kotlin : Délégation, Générique

Temps : 45 min.
Diffiulté : *

L'objectif est de mettre en pratique le concept de :

  1. Délégation
  2. Générique

1. Délégation

Délégation de fonction

Il s'agit de créer une classe, une interface contenant une fonction et d'ajouter la délégation sur l'interface.

  1. Dans le package agua, créez un nouveau package crab.
  2. Dans le package agua.crab, créez un nouveau fichier HermitAndCrab.kt
  3. Créez une nouvelle interface CrabAction :
  4.   
      interface CrabAction {
          fun pinch()
      }
      
      
  5. Créez une classe Crab, elle implémente l'interface CrabAction :
  6.   
      class Crab : CrabAction {
          override fun pinch() = println("_-<>  pinch <>-_")
      }
      
      
  7. Ajouter une classe PrintingCrabAction, elle implémente CrabAction :
  8.   
      class PrintingCrabAction(val crabAction: String) : CrabAction {
        override fun pinch() {
            println(crabAction)
        }
      }
      
      
  9. Ajouter la délégation d'interface pour CrabAction :
  10.   
      class Crab : CrabAction by PrintingCrabAction("_-<>  pinch <>-_")
      
      
  11. Créez une fontion playWithCrab() pour tester (faites pincer le crabe), appellez là dans un main
  12. Exécutez votre programme

Délégation de propriété avec Singleton

Il s'agit de créer une classe, une interface avec propriété, une classe singleton et d'ajouter la délégation sur l'interface via le singleton.

  1. Créez une nouvelle interface GastropodShell :
  2.   
      interface GastropodShell {
          val shell: String
      }
      
      
  3. Créez une classe HermitCrab, elle implémente l'interface GastropodShell :
  4.   
      class HermitCrab : GastropodShell {
        override val shell = "SHELL"
      }
      
      
  5. Ajoutez dans playWithCrab() une instance de HermitCrab pour tester (affichez la carapace du bernard l'hermite), exécutez le main
  6. Créez une classe singleton Shell, elle implémente l'interface GastropodShell :
  7.   
      object Shell : GastropodShell {
        override val shell = "((.))"
      }
      
      
  8. Ajouter la délégation d'interface pour GastropodShell :
  9.   
      class HermitCrab : GastropodShell by Shell
      
      
  10. Exécutez votre programme

2. Générique

Il s'agit de créer des listes d'objet afin de mettre en pratique le concept de générique. Aussi il s'agit de créer des classes d'héritage pour mettre en évidence le principe de covariance et contravariance.

Principe de Covariance

  1. Dans le package agua, créez un nouveau package beach.
  2. Dans le package agua.beach, créez un nouveau fichier BeachEquipment.kt
  3. Créez une nouvelle classe d'héritage BeachEquipment :
  4.     
        open class BeachEquipment(val name: String) {
            fun removeSand() {}
        }
        
        
  5. Créez deux classes de données Towel et Umbrella, des sous classes de BeachEquipment :
  6.     
        data class Towel(val towelName: String) : BeachEquipment(towelName)
        data class Umbrella(val umbrellaName: String) : BeachEquipment(umbrellaName)
        
        
  7. Dans une fonction main, créez une liste de Umbrella, de Towel et de BeachEquipment :
  8.     
        fun main() {
          val umbrellaList = listOf(Umbrella("Macha umbrella"), Umbrella("Red umbrella"), Umbrella("White Umbrella"))
          val towelList = listOf(Towel("Macha Towel"), Towel("Gugus towel"))
          val beachParty = umbrellaList + towelList
          print(beachParty)
        }
        
        
  9. Créez une fonction removeSand() prenant en paramètre une liste de BeachEquipment, elle s'applique à la classe parent et donc aux sous classes de la classe parent, selon le principe de covariance :
  10.     
        fun removeSand(equipmentList: List<BeachEquipment>) {
          equipmentList.forEach {
              it.removeSand()
              println(it.name + " cleaned !")
          }
        }
        
        
  11. Appelez cette fonction dans le main, exécutez

Principe de Contravariance

  1. Dans BeachEquipment.kt, créez un comparateur de BeachEquipment :
  2.     
        val compareByNames = Comparator { a: BeachEquipment, b: BeachEquipment ->
          a.name.length - b.name.length
        }
        
        
  3. Dans le main triez les éléments de beachParty via ce comparateur :
  4.     
        beachParty.sortedWith(compareByNames).forEach(::println)
        
        
  5. Exécutez, observez le résultat

Finalement, le code Kotlin peut être épuré avec la délégation de :

De plus, il est pratique d'utiliser le générique pour le traitement de liste, aussi afin de légiférer ces traitements, il est utilisé le principe de :

Références

developer.android.com: Using Classes and Objects in Kotlin
medium.com: Kotlin Covariance and Contravariance