Quel est le message qui passe dans OO?


35

J'ai étudié la programmation OO, principalement en C ++, C # et Java. Je pensais que je comprenais bien l’encapsulation, l’héritage et le polymorphisme (ainsi que la lecture de nombreuses questions sur ce site).

Une chose semble apparaître ici et il y a le concept de "transmission de message". Apparemment, c'est quelque chose qui n'est pas utilisé pendant la programmation OO dans les langages traditionnels d'aujourd'hui, mais supporté par Smalltalk.

Mes questions sont:

  • Qu'est-ce qu'un message qui passe? (Quelqu'un peut-il donner un exemple concret?)
  • Existe-t-il une prise en charge de ce "transfert de message" en C ++, C # ou Java?

4
J'ai répondu à cette question il y a peu de temps: stackoverflow.com/a/3104741/10259
Frank Shearar

1
Avez-vous lu l'article de Wikipedia ?
Yannis

4
À mon humble avis, Objective-C pourrait être qualifié de langue dominante. Au moins autant que C #.
mouviciel

Je suis d’accord avec ça, j’affirmais les langues "grand public" de mon expérience
Tom

Un appel de fonction membre est une implémentation de la transmission d'un message. Le message transmis est identifié par le nom de la fonction et inclut les informations des paramètres. La liaison tardive permet à la classe réceptrice de traiter le même message différemment des autres classes. Ce n'est pas ce que voulaient les créateurs de Simula, et de nombreuses personnes s'opposeraient à ce qu'on l'appelle passe de message et déclare (avec raison) que le passage de message est un élément clé qui différencie Simula, mais que les appels de fonctions des membres continuent à faire essentiellement de même emploi.
Steve314

Réponses:


60

Qu'est-ce qu'un message qui passe? (Quelqu'un peut-il donner un exemple concret?)

La transmission de messages signifie simplement que (à un niveau très abstrait) le mécanisme fondamental de l'exécution d'un programme est constitué par les objets qui s'envoient des messages. Le point important est que le nom et la structure de ces messages ne sont pas nécessairement fixés au préalable dans le code source et peuvent être eux-mêmes des informations supplémentaires. C'est une partie importante de ce que Alan Kay avait initialement envisagé comme "programmation orientée objet".

Existe-t-il une prise en charge de ce "transfert de message" en C ++, C # ou Java?

Ces langages implémentent une version limitée du message passant par les appels de méthodes. Limité car l'ensemble des messages pouvant être envoyés est limité aux méthodes déclarées dans une classe. L’avantage de cette approche est qu’elle peut être mise en œuvre de manière très efficace et qu’elle permet une analyse de code statique très détaillée (ce qui offre toutes sortes d’avantages utiles, tels que l’achèvement de code).

Inversement, les langages qui implémentent la "vraie" transmission de messages ont souvent aussi des définitions de méthodes, ce qui est un moyen pratique d'implémenter des gestionnaires de messages, mais permet aux classes d'implémenter des gestionnaires de messages plus souples permettant à l'objet de recevoir des "appels de méthodes" avec des noms arbitraires (non corrigés). au moment de la compilation).

Un exemple dans Groovy qui démontre la puissance de ce concept:

def xml = new MarkupBuilder(writer)
xml.records() {
  car(name:'HSV Maloo', make:'Holden', year:2006) {
    country('Australia')
    record(type:'speed', 'Production Pickup Truck with speed of 271kph')
  }
}

va produire ce XML:

<records>
  <car name='HSV Maloo' make='Holden' year='2006'>
    <country>Australia</country>
    <record type='speed'>Production Pickup Truck with speed of 271kph</record>
  </car>
</records>

Notez que records, car, countryet recordsont syntaxiquement appels de méthode, mais il n'y a pas de méthodes de ce nom défini dans MarkupBuilder. Au lieu de cela, il dispose d'un gestionnaire de messages catchall qui accepte tous les messages et interprète les noms de message comme le nom d'un élément XML, les paramètres comme attributs et les fermetures comme éléments enfants.


+1 directement au point de réponse. Accepté pour l'exemple de code. Merci pour votre aide :)
Tom

Donc, ne pourrait-il pas simplement être mis en œuvre avec un langage simple sendMessage(property_name, Array of arguments)et getMessage(property_name, Array of arguments)statique?
Pacerier

1
@ Pacerier: bien sûr, mais cela combine les inconvénients des deux approches: vous perdez la sécurité de type et vous avez toujours "sendMessage" qui pollue le code partout, de sorte que vous n'obtenez pas la syntaxe élégante.
Michael Borgwardt

Serait-il plus juste de dire que, dans l'exemple Groovy, le gestionnaire de messages reçoit un message plutôt qu'un appel de méthode? Vous avez initialement placé des guillemets autour de l'expression "appel de méthode", mais dans votre dernière phrase, vous dites qu'il "accepte toutes les méthodes ", plutôt que "messages".
Adam Zerner

@ AdamZerner: vous avez raison, je l'ai corrigé.
Michael Borgwardt

28

La transmission de message est une manière différente de gérer le besoin en code OO pour un objet d'obtenir un autre objet (ou potentiellement lui-même) pour faire quelque chose.

Dans la plupart des langages modernes issus de l'approche C ++, nous le faisons avec des appels de méthodes. Dans ce cas, l'objet appelé (via sa définition de classe) met une grande liste des méthodes qu'il accepte, puis le codeur de l'objet appelant écrit simplement l'appel:

public void doSomething ( String input )
...
other_object.dosomething ( local )

Pour les langages à typage statique, le compilateur peut alors vérifier le type de la chose appelée et confirmer que la méthode a été déclarée. Pour les langages à typage dynamique, cette opération est effectuée au moment de l'exécution.

Mais ce qui se passe essentiellement, c’est qu’un ensemble de variables est envoyé à un bloc de code spécifique.

Message en passant

Dans les langues de transmission de messages (telles que Objective C) au lieu de méthodes, il y a des destinataires, mais dans l’ensemble, l’approche consistant à les définir et à les appeler est sensiblement la même - la différence réside dans la manière dont elle est traitée.

Dans une langue de message passé, le compilateur peut vérifier que le destinataire que vous avez appelé existe, mais au pire, un avertissement apparaît pour vous avertir qu'il n'est pas sûr qu'il soit là. En effet, au moment de l'exécution, un bloc de code sur l'objet récepteur sera appelé en passant à la fois le groupe de variables et la signature du destinataire que vous souhaitez appeler. Ce bloc de code recherche alors le destinataire et l’appelle. Cependant, si le destinataire n'existe pas, le code renverra simplement une valeur par défaut.

En conséquence, l’une des bizarreries trouvées lors du passage de C ++ / Java -> Objective C comprend que vous pouvez "appeler une méthode" sur un objet qui n’a pas été déclaré dans le type de compilation et n’existait même pas le le type d'exécution ... et que l'appel ne se traduirait pas par une exception mais par un résultat renvoyé.

Les avantages de cette approche sont qu’elle aplatit la hiérarchie des sous-classes et évite la plupart des besoins en interfaces / héritage multiple / types de canard. Cela permet également aux objets de définir le comportement par défaut quand on leur demande de faire quelque chose pour laquelle ils n'ont pas de récepteur (généralement "si je ne le fais pas, transférez la demande à cet autre objet"). Il peut également simplifier la liaison aux rappels (par exemple, pour les éléments d'interface utilisateur et les événements programmés), en particulier avec des langages statiques tels que Java (le bouton appelle alors le destinataire "runTest" plutôt que la méthode "actionPerformed" de la classe interne). "RunTestButtonListener" qui effectue l'appel pour vous).

Cependant, il semblerait que le développeur ait besoin de vérifier que l'appel qu'il pense est en train de passer sur le bon objet avec le bon type et de transmettre les bons paramètres dans le bon ordre, car le compilateur pourrait ne pas le faire. vous avertir et il fonctionnera parfaitement au moment de l'exécution (en renvoyant une réponse par défaut). On peut également affirmer que les performances supplémentaires résultent de la recherche supplémentaire et du dépassement des paramètres.

De nos jours, les langages à typage dynamique peuvent donner beaucoup d'avantages du message passé à OO avec moins de problèmes.


1
J'aime cette réponse - explique les différences et leurs implications.
HappyCat

@Gavin, est-ce donc exactement la même chose que le gestionnaire de méthodes dynamiques de PHP et Javascript ?
Pacerier

11

Les architectures de transmission de messages sont simplement des systèmes dans lesquels chaque composant est indépendant des autres, avec un mécanisme commun pour la transmission de données entre eux. Vous pouvez considérer les appels de méthode comme une forme de transmission de message, mais ce n'est pas pratique, cela confond le problème. En effet, si vous avez une classe avec des méthodes bien définies et un code appelant ces méthodes, le tout doit être compilé ensemble, couplant ainsi le code et l'objet. vous pouvez voir à quel point il est proche (lorsqu'un message est transmis et que le compilateur applique la correction, mais il perd une grande partie de la flexibilité d'un système découplé).

Les architectures de transmission de messages permettent souvent d'ajouter des objets au moment de l'exécution et, le plus souvent, de rediriger les messages vers un ou plusieurs objets. Ainsi, je peux avoir du code qui diffuse un message "data x is updated" à tous les objets chargés dans le système, et chacun d'entre eux peut prendre les mesures qu'il souhaite avec ces informations.

Le Web est un exemple étrange. HTTP est un système de transmission de messages - vous passez un verbe de commande et un "paquet de données" à un processus serveur. (par exemple, GET http: \ myserver \ url) Ni votre navigateur, ni le serveur Web ne se soucient de quoi que ce soit des données que vous envoyez ou de l'endroit où vous les envoyez. Le serveur le transmettra au code qui emballera un autre "paquet" de données et vous le renverra. Aucun des composants de ce système ne sait quoi que ce soit du travail des autres ou de ce qu'ils font, ils connaissent simplement le protocole utilisé pour la communication du message.


@gbjbannb, Besoin de quelques explications de pseudo-codes ....
Pacerier
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.