En programmation orientée objet , la délégation fait référence à l'évaluation d'un membre ( propriété ou méthode ) d'un objet (le récepteur) dans le contexte d'un autre objet d'origine (l'expéditeur). La délégation peut être effectuée explicitement, en transmettant les responsabilités de l'objet expéditeur à l'objet destinataire, ce qui peut être fait dans n'importe quel langage orienté objet ; ou implicitement, par les règles de recherche de membres du langage, ce qui nécessite la prise en charge de la fonctionnalité par le langage. La délégation implicite est la méthode fondamentale pour la réutilisation du comportement dans la programmation basée sur des prototypes , correspondant à l'héritage dans la programmation basée sur des classes . Les langages les plus connus qui prennent en charge la délégation au niveau du langage sont Self , qui intègre la notion de délégation via sa notion d' emplacements parents mutables qui sont utilisés lors de la recherche de méthode sur les appels self, et JavaScript ; voir Délégation JavaScript .
Le terme délégation est également utilisé de manière vague pour diverses autres relations entre objets ; voir délégation (programmation) pour plus d'informations. Les concepts fréquemment confondus sont la simple utilisation d'un autre objet, plus précisément appelée consultation ou agrégation ; et l'évaluation d'un membre sur un objet en évaluant le membre correspondant sur un autre objet, notamment dans le contexte de l'objet récepteur, qui est plus précisément appelé transfert (lorsqu'un objet wrapper ne se transmet pas à l'objet wrappé). Le modèle de délégation est un modèle de conception de logiciel pour la mise en œuvre de la délégation, bien que ce terme soit également utilisé de manière vague pour la consultation ou le transfert.
Aperçu
Ce sens de la délégation en tant que fonctionnalité du langage de programmation utilisant les règles de recherche de méthode pour la répartition des soi-disant auto-appels a été défini par Lieberman dans son article de 1986 « Utilisation d'objets prototypiques pour implémenter un comportement partagé dans des systèmes orientés objet ».
La délégation dépend de la liaison dynamique , car elle nécessite qu'un appel de méthode donné puisse invoquer différents segments de code au moment de l'exécution . Elle est utilisée dans macOS (et son prédécesseur NeXTStep ) comme moyen de personnaliser le comportement des composants du programme. Elle permet des implémentations telles que l'utilisation d'une seule classe fournie par le système d'exploitation pour gérer les fenêtres, car la classe prend un délégué spécifique au programme et peut remplacer le comportement par défaut selon les besoins. Par exemple, lorsque l'utilisateur clique sur la case de fermeture, le gestionnaire de fenêtres envoie au délégué un appel windowShouldClose: et le délégué peut retarder la fermeture de la fenêtre, s'il existe des données non enregistrées représentées par le contenu de la fenêtre.
La délégation peut être caractérisée (et distinguée de la transmission ) comme une liaison tardive de soi-même :
... les messages envoyés à la variable
self(outhis) dans le parent « reviendront » à l'objet qui a reçu le message à l'origine.
Autrement dit, la selfdéfinition d'une méthode dans l'objet récepteur n'est pas statiquement liée à cet objet au moment de la définition (comme au moment de la compilation ou lorsque la fonction est attachée à un objet), mais plutôt au moment de l'évaluation , elle est liée à l' objet d'origine .
Il a été avancé que la délégation peut dans certains cas être préférée à l'héritage pour rendre le code du programme plus lisible et compréhensible. Bien que la délégation explicite soit assez répandue, relativement peu de langages de programmation majeurs implémentent la délégation comme modèle alternatif à l'héritage. La relation précise entre délégation et héritage est compliquée ; certains auteurs les considèrent comme équivalents, ou l'un comme un cas particulier de l'autre.
Prise en charge linguistique pour la délégation
Dans les langages qui prennent en charge la délégation via des règles de recherche de méthode, la répartition des méthodes est définie de la même manière que pour les méthodes virtuelles dans l'héritage : c'est toujours la méthode la plus spécifique qui est choisie pendant la recherche de méthode. Par conséquent, c'est l' entité réceptrice d'origine qui est le début de la recherche de méthode même si elle a transmis le contrôle à un autre objet (via un lien de délégation, et non une référence d'objet).
La délégation a l'avantage de pouvoir avoir lieu au moment de l'exécution et d'affecter uniquement un sous-ensemble d'entités d'un certain type, et peut même être supprimée au moment de l'exécution. L'héritage, en revanche, cible généralement le type plutôt que les instances et est limité au moment de la compilation. D'un autre côté, l'héritage peut être vérifié statiquement, alors que la délégation ne peut généralement pas l'être sans génériques (bien qu'une version restreinte de la délégation puisse être statiquement typée ). La délégation peut être qualifiée d'« héritage au moment de l'exécution pour des objets spécifiques ».
Voici un exemple de pseudo-code dans un langage de type C# / Java :
classe A { void foo () { // "this" également connu sous les noms "current", "me" et "self" dans d'autres langages this . bar (); } void barre () { print ( "a.bar" ); } } classe B { délégué privé A a ; // lien de délégation public B ( A a ) { ceci . a = a ; } void foo () { a . foo (); // appeler foo() sur l'instance a } void barre () { print ( "b.bar" ); } } a = new A (); b = new B ( a ); // établir une délégation entre deux objets
L'appel b.foo()entraînera l'affichage de b.barthis , car fait référence à l' objet récepteur d'origineb , , dans le contexte de a. L'ambiguïté résultante de thisest appelée schizophrénie d'objet .
En traduisant l'implicite thisen paramètre explicite, l'appel (dans B, avec aun délégué) a.foo()se traduit par A.foo(b), en utilisant le type de arésolution de méthode pour, mais l'objet délégant bpour l' thisargument.
En utilisant l'héritage, le code analogue (en utilisant des majuscules pour souligner que la résolution est basée sur des classes et non sur des objets) est :
classe A { void foo () { ceci . bar (); } void barre () { print ( "A.bar" ); } } la classe B étend A { public B () {} void foo () { super . foo (); // appel foo() de la superclasse (A) } void barre () { print ( "B.bar" ); } } b = nouveau B ();
L'appel b.foo()donnera comme résultat B.bar . Dans ce cas, thisil n'y a aucune ambiguïté : il y a un seul objet, b, et this.bar()se résout en la méthode de la sous-classe.
Les langages de programmation en général ne prennent pas en charge cette forme inhabituelle de délégation en tant que concept de langage, mais il existe quelques exceptions .
Double héritage
Si le langage prend en charge à la fois la délégation et l'héritage, on peut réaliser un double héritage en utilisant les deux mécanismes en même temps, comme dans
la classe C étend A { délégationlink D d ; }
Cela nécessite des règles supplémentaires pour la recherche de méthode, car il existe désormais potentiellement deux méthodes qui peuvent être désignées comme les plus spécifiques (en raison des deux chemins de recherche).
Domaines connexes
La délégation peut être décrite comme un mécanisme de bas niveau permettant de partager du code et des données entre entités. Elle constitue ainsi la base d'autres constructions de langage. Les langages de programmation orientés rôles ont notamment utilisé la délégation, mais les plus anciens ont surtout utilisé l'agrégation tout en prétendant utiliser la délégation. Cela ne doit pas être considéré comme de la triche, mais simplement comme la définition plurielle de ce que signifie la délégation (comme décrit ci-dessus).
Plus récemment, des travaux ont également été réalisés sur la distribution de la délégation, de sorte que, par exemple, les clients d'un moteur de recherche (recherche de chambres d'hôtel bon marché) peuvent utiliser une entité partagée utilisant la délégation pour partager les meilleurs résultats et les fonctionnalités générales réutilisables.
La délégation a également été suggérée pour la résolution de conseils dans la programmation orientée aspect par Ernst et Lorenz en 2003.