Différences entre messages et méthodes?


13

Dans Objective C, vous avez le concept d'envoyer des messages à d'autres objets, et c'est très similaire à l'appel de méthode dans des langages comme C # et Java.

Mais quelles sont exactement les différences subtiles? Comment dois-je penser à la messagerie quand je pense à mon code?

Remarque: Juste un peu de contexte ici, je suis un développeur C # / Java essayant de comprendre certains concepts sur l'objectif C.


2
Puisqu'il s'agit de langues différentes, les différences ne sont pas subtiles. Ce sont des langues différentes. "en pensant à mon code"? Quel code? Lorsque vous pensez à Java ou C #, vous ne pensez pas aux messages. Vous pensez aux méthodes. Pouvez-vous préciser comment des langues sans rapport avec des concepts sans rapport peuvent avoir des différences "subtiles"?
S.Lott

1
Veuillez poser votre question à stackoverflow.com
Amir Rezaei

1
Cette question devrait-elle vraiment être sur StackOverflow? C'est une question sur les concepts de programmation, pas un problème sur le code que j'ai. Peut-être que je me trompe, je ne sais pas - les frontières s'estompent ...
Vidar

1
@Vidar, la question n'est pas subjective. Vous recherchez une définition de manuel. Les programmeurs sont plus pour les opinions, l'expérience et les questions subjectives.
Stephen Furlani

1
OK - existe-t-il un moyen pour que le modérateur déplace cette question vers StackOverflow?
Vidar

Réponses:


10

Un message est le nom d'un sélecteur et les paramètres de ce sélecteur.

Un sélecteur est un symbole.

Une méthode est un morceau de code dans une classe identifiée par un sélecteur.

En d'autres termes, [foo bar: baz]dit "envoyer le message appelé @selector(bar:)avec le paramètre bazà l'objet foo. Vous pouvez envoyer ce message à de nombreux objets différents.

En revanche, la méthode bar: pour un Foopourrait ressembler à

-(int)bar:(int)n {
  return n + 1;
}

mais pour un FooTwopourrait ressembler

-(int)bar:(int)n {
  return n + 2;
}

(J'espère avoir la bonne syntaxe; cela fait un moment que je n'ai pas touché Objective-C pour la dernière fois.)

Lorsque vous envoyez le message, le noyau Objective-C envoie le message à fooqui décide s'il comprend le message. Il décide cela selon qu'il peut trouver une méthode identifiée par ce sélecteur.

Deux méthodes avec le même nom et un message.

Il est également possible pour un objet de simplement transmettre un message particulier (ou un ensemble de messages) à un autre objet pour traitement. Dans ce cas, vous envoyez un message à cet objet proxy, qui n'a aucune méthode pour faire correspondre ce message , et le proxy transfère le message à son objet encapsulé.


alors ... un message est lorsque vous appelez une dispinterface (a.invoke selector, args) et une méthode est lorsque vous appelez une interface (a.methodName)? Cela ne ferait-il pas que java, JavaScript, tous les langages dynamiques aient des messages parce que tout se passe via une double interface plutôt que des sauts directs et un décalage en sauts vtable)?
Dmitry

3

D'un point de vue purement théorique, il n'y a aucune différence entre les deux - il y a eu un certain nombre de preuves formelles montrant que les deux sont complètement équivalentes, et l'une ou l'autre peut être mise en œuvre entièrement en fonction de l'autre.

D'un point de vue légèrement moins théorique, il y a une différence possible: dans une implémentation typique, la table des fonctions virtuelles est allouée statiquement et le contenu de chaque table est fixé au moment de la compilation. La recherche de messages, en revanche, se fait généralement avec une sorte d'objet semblable à une carte, qui est généralement dynamique, ce qui signifie que vous pouvez le modifier au moment de l'exécution. Cela rend relativement facile l'ajout d'une nouvelle réponse à un message dans une classe existante. Malheureusement, dans la plupart des cas, cela reste principalement théorique. Tout d'abord, vous avez essentiellement affaire à du code auto-modifiable, ce que la plupart des gens ont décidé longtempsil y a longtemps. Deuxièmement, pour le rendre très significatif, vous devez à peu près être capable de compiler du nouveau code dans la classe existante pour répondre au nouveau message que vous supportez. Sans cela, tout ce que vous gagnez est la possibilité d'ajouter dynamiquement un nouveau nom pour une méthode existante.

Comme l'indique la fin du paragraphe précédent, d'un point de vue vraiment pratique, il y a très peu de différence entre les deux. Ce sont simplement deux (très légèrement) façons différentes de supporter la liaison tardive. Bien que la recherche basée sur les messages soit généralement un peu plus lente, il serait assez inhabituel que la différence soit vraiment significative. Dans la plupart des cas, ce ne sont que deux façons différentes d'accomplir la même chose.


2
Avez-vous des références montrant les preuves? J'aimerais jeter un oeil. Il y a une grande différence entre l'invocation de la méthode Java et l'envoi de messages Smalltalk, non seulement à cause de la liaison tardive, mais aussi à cause du découplage de l'expéditeur et du destinataire: vous ne pouvez pas dire si le destinataire d'un message le traite ou transfère le message par exemple.
Frank Shearar

1

Dans Objective-C, les messages sont liés tardivement. Autrement dit, ils sont résolus au moment de l'exécution. C # prend en charge une construction similaire via le mot clé Dynamic qui déclare également qu'un objet est lié tardivement.


0

Habituellement, les appels de méthode sont résolus au moment de la compilation (sauf si vous utilisez la réflexion en Java), tandis que les messages dans Objective C sont distribués au moment de l'exécution.


2
Si les appels de méthode sont résolus au moment de la compilation, vous n'utilisez pas la POO, vous utilisez du sucre syntaxique pour les fonctions surchargées prenant un structpremier paramètre. Le bindung tardif est une partie essentielle du polymorphisme et donc de la POO.

2
Oui. Mais vous pouvez toujours coder un appel de méthode contre quelque chose (en Java) qui est bien connu au moment de la compilation. L'appel de MyObject.foo () donnera une erreur si MyObject ou MyInterface n'a pas de méthode foo () définie. ObjC permettra de vous envoyer un message 'foo' pour objecter MyObject - et si MyObject n'a pas de 'foo', cela bombardera au moment de l'exécution.
Heiko Rupp

Je pensais que l'objectif C était un langage compilé?
Vidar

1
Cela n'est pas lié à la liaison précoce / tardive (typage dynamique vs typage structurel - dans votre exemple, les appels de méthode sont vérifiés au moment de la compilation mais pas nécessairement envoyés ). @Vidar: Oui, mais cela ajoute de la magie pour les fonctionnalités dynamiques. Vous pouvez également compiler Python.

@Vidar: Ce n'est pas un problème de compilation vs d'interprétation, mais plutôt statique vs dynamique. Dans les langages OOP statiques comme Java, le compilateur vérifie qu'une classe définit une méthode pendant la phase de compilation. Dans un langage à typage dynamique comme Objective-C, les messages sont transmis lors de l'exécution.
mipadi

-1

Les messages sont soit gérés par le noyau, soit par le langage lui-même (pour ObjC par exemple, il existe un très petit code assembleur qui le fait).

Dans le noyau linux par exemple, les messages sont faits avec des appels système / fonction: vous pouvez les trouver si vous cherchez sur la programmation système unix.

La principale différence entre un appel de méthode et un message est la suivante:

  • un appel de méthode ne se produit que dans votre code: dans ASM, il est traduit par un PUSH des arguments passés.

  • un message du noyau est principalement quelque chose envoyé au noyau qui est suivi et renvoyé à un certain processus. Je peux les confondre avec des pipes, mais peu importe: sachez qu'il existe déjà un mécanisme qui vous permet d'exécuter plusieurs programmes en même temps et de communiquer en même temps. Bien sûr, n'espérez pas que cela fonctionnera de la même manière sur Windows ou d'autres OS.


Ce n'est pas du "passage de message" car cela s'applique aux langages de programmation.
mipadi
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.