Par contre, dès que le nombre de fonctions concernées explose, le code devient particulièrement stupide et pénible à maintenir. Malgré plusieurs propositions rien n'a été fait en Java pour simplifier le travail du développeur. Heureusement, les environnements de développement proposent un petit outil pour générer le code automatiquement, mais la maintenance reste plus ou moins manuelle.
Avec Kotlin, c'est on ne peut plus simple. La seule contrainte est de définir les fonctions qui seront déléguées dans une interface. La création d'interface est par ailleurs une pratique recommandée. Ensuite il suffit quand on hérite d'une interface de spécifier l'objet vers qui déléguer les appels et c'est fini !
interface I {
fun travaille()
fun pause()
}
class Ouvrier : I {
override fun travaille() = println ("Je travaille")
override fun pause() = println ("Je fais une pause")
}
open class Chef(employé: I) : I by employé
fun main(args: Array<String>): Unit {
val c = Chef(Ouvrier())
c.travaille()
c.pause()
}
Un objet de la classe Chef délègue tous les appels aux fonctions définie dans I vers un autre objet. Il suffit de rajouter by employé pour déléguer les appels vers l'objet sous jacent.
Bien sûr la classe Chef peut définir d'autres méthodes, hériter d'autres classes ou interface, voir déléguer vers d'autres objets de la même manière.
Attention, pour redéfinir une fonction déléguée, on ne peut pas le faire directement dans la classe Chef. Une autre classe est alors nécessaire.
Exemple :
open class SuperViseur(équipe: I) : Chef(équipe) {
override fun pause() {
val début = Instant.now()
super.pause()
println ("Temps d'éxecution ${Duration.between(début, Instant.now())}")
}
}
fun main(args: Array<String>): Unit {
val m = SuperViseur(Chef(Ouvrier()))
m.travaille()
m.pause()
}
J'ai l'habitude d'encapsuler les resources externes dans des interfaces qui peuvent parfois enfler sans retenue. Après je sépare le code dans des couches bien séparées : l'une fait le lien avec la ressource, les autres gèrent les droits d'accès, les accès concurrents, des caches de données, des mesures de performance, etc... Typiquement, la première couche hérite directement de l'interface, les suivantes d'une classe de délégation pure dont je redéfinie uniquement certaines routines suivant le besoin. Je n'ai plus besoin maintenant de maintenir cette classe de délégation.
Aucun commentaire:
Enregistrer un commentaire