Unterschiede zwischen Nachrichten und Methoden?

13

In Objective C haben Sie das Konzept, Nachrichten an andere Objekte zu senden, und dies ist sehr ähnlich zu Methodenaufrufen in Sprachen wie C # und Java.

Aber was genau sind die subtilen Unterschiede? Wie sollte ich an Nachrichten denken, wenn ich an meinen Code denke?

Hinweis: Nur ein bisschen Hintergrundwissen, ich bin ein C # / Java-Entwickler, der versucht, einige Konzepte zu Objective C zu verstehen.

Vidar
quelle
2
Da sie alle verschiedene Sprachen sind, sind die Unterschiede nicht subtil. Sie sind verschiedene Sprachen. "Wenn ich an meinen Code denke"? Welcher Code? Wenn Sie an Java oder C # denken, denken Sie nicht an Nachrichten. Sie denken über Methoden nach. Können Sie klären, wie nicht verwandte Sprachen mit nicht verwandten Konzepten "subtile" Unterschiede haben können?
S.Lott
1
Bitte stellen Sie Ihre Frage an stackoverflow.com
Amir Rezaei
1
Sollte diese Frage wirklich auf StackOverflow stehen? Es geht um Programmierkonzepte, nicht um ein Problem mit Code, den ich habe. Vielleicht irre ich mich, ich weiß nicht - die Grenzen verschwimmen ...
Vidar
1
@Vidar, die Frage ist nicht subjektiv. Sie suchen eine Lehrbuchdefinition. Programmierer sind mehr für Meinungen, Erfahrungen und subjektive Fragen.
Stephen Furlani
1
OK - gibt es eine Möglichkeit, den Moderator zu veranlassen, diese Frage in StackOverflow zu verschieben?
Vidar

Antworten:

10

Eine Nachricht ist der Name eines Selektors und die Parameter für diesen Selektor.

Ein Selektor ist ein Symbol.

Eine Methode ist ein Stück Code in einer Klasse, die durch einen Selektor identifiziert wird.

Mit anderen Worten [foo bar: baz]: "Senden Sie die @selector(bar:)mit parameter aufgerufene Nachricht bazan object foo. Sie können diese Nachricht an viele verschiedene Objekte senden.

Im Gegensatz dazu könnte die Methode bar: für a so Fooaussehen

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

aber für eine FooTwokönnte aussehen

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

(Ich hoffe, ich habe die richtige Syntax; es ist schon eine Weile her, seit ich Objective-C das letzte Mal berührt habe.)

Wenn Sie die Nachricht senden, leitet der Objective-C-Kernel die Nachricht weiter, an foodie entschieden wird, ob die Nachricht verstanden wird. Dies wird basierend darauf entschieden, ob eine von diesem Selektor identifizierte Methode gefunden wird.

Zwei gleichnamige Methoden und eine Meldung.

Es ist auch möglich, dass ein Objekt eine bestimmte Nachricht (oder eine Reihe von Nachrichten) zur Verarbeitung einfach an ein anderes Objekt weiterleitet. In diesem Fall senden Sie eine Nachricht an dieses Proxy-Objekt, für das es keine entsprechenden Methoden gibt , und der Proxy leitet die Nachricht an das umschlossene Objekt weiter.

Frank Shearar
quelle
Also ... eine Meldung, wenn Sie ein Dispatch-Interface aufrufen (ein Aufrufselektor, args) und eine Methode, wenn Sie ein Interface aufrufen (ein Methodenname)? Wäre das nicht so, dass Java, JavaScript und alle dynamischen Sprachen Nachrichten haben, weil alles über die duale Schnittstelle geschieht und nicht durch direkte Sprünge und Versatz in vtable-Sprünge)?
Dmitry
3

Rein theoretisch gesehen gibt es keinen Unterschied zwischen den beiden - es gab eine Reihe formaler Beweise dafür, dass die beiden völlig gleichwertig sind und beide vollständig im Hinblick auf die anderen implementiert werden können.

Aus einer etwas weniger theoretischen Sicht gibt es einen möglichen Unterschied: In einer typischen Implementierung wird die virtuelle Funktionstabelle statisch zugewiesen und der Inhalt jeder vtable wird zur Kompilierungszeit festgelegt. Im Gegensatz dazu wird die Nachrichtensuche in der Regel mit einem map-ähnlichen Objekt durchgeführt, das in der Regel dynamisch ist und das heißt, Sie können es zur Laufzeit ändern. Dadurch ist es relativ einfach, einer Nachricht in einer vorhandenen Klasse eine neue Antwort hinzuzufügen. Leider bleibt dies in den meisten Fällen meist theoretisch. Zuerst Sie es zu tun im Grunde mit selbst-modifizierenden Code, der die meisten Menschen entschieden eine ziemlich schlechte Idee war eine langevor einiger Zeit. Zweitens, um es sehr aussagekräftig zu machen, müssen Sie in der Lage sein, neuen Code in die vorhandene Klasse zu kompilieren, um auf die neue Nachricht zu antworten, die Sie unterstützen. Andernfalls können Sie einer vorhandenen Methode nur dynamisch einen neuen Namen hinzufügen.

Wie am Ende des vorhergehenden Abschnitts angedeutet, gibt es unter einem wirklich praktischen Gesichtspunkt kaum einen Unterschied zwischen den beiden. Es handelt sich lediglich um zwei (sehr geringfügig) unterschiedliche Möglichkeiten, das späte Binden zu unterstützen. Obwohl die nachrichtenbasierte Suche im Allgemeinen etwas langsamer ist, ist es ziemlich ungewöhnlich, dass der Unterschied wirklich signifikant ist. Für die meisten praktischen Zwecke gibt es nur zwei verschiedene Möglichkeiten, um dasselbe Ziel zu erreichen.

Jerry Sarg
quelle
2
Haben Sie Referenzen, die die Beweise zeigen? Ich würde gerne einen Blick darauf werfen. Es gibt einen großen Unterschied zwischen Javas Methodenaufruf und Smalltalks Nachrichtenversand, nicht nur wegen der späten Bindung, sondern auch wegen der Entkopplung von Absender und Empfänger: Sie können nicht feststellen, ob der Empfänger einer Nachricht diese verarbeitet oder weiterleitet zum Beispiel.
Frank Shearar
1

In Objective-C sind Nachrichten spät gebunden. Das heißt, sie werden zur Laufzeit aufgelöst. C # unterstützt ein ähnliches Konstrukt über das Schlüsselwort Dynamic, das ein Objekt auch als spät gebunden deklariert.

Michael Brown
quelle
0

Normalerweise werden Methodenaufrufe zur Kompilierungszeit aufgelöst (es sei denn, Sie verwenden Reflection in Java), während Nachrichten in Objective C zur Laufzeit abgesetzt werden.

Heiko Rupp
quelle
2
Wenn Methodenaufrufe aufgelöst werden, während sie kompiliert werden, verwenden Sie kein OOP. Sie verwenden syntaktischen Zucker für überladene Funktionen, die einen structals ersten Parameter verwenden. Die späte Bindung ist ein wesentlicher Bestandteil des Polymorphismus und damit des OOP.
2
Ja. Dennoch können Sie einen Methodenaufruf nur für etwas (in Java) codieren, das zum Zeitpunkt der Kompilierung bekannt ist. Der Aufruf von MyObject.foo () führt zu einer Fehlermeldung, wenn für MyObject oder MyInterface keine Methode foo () definiert ist. ObjC ermöglicht es Ihnen, eine Nachricht 'foo' an Object MyObject zu senden - und wenn MyObject kein 'foo' hat, wird dies zur Laufzeit bombardiert.
Heiko Rupp
Ich dachte, Ziel C sei eine kompilierte Sprache?
Vidar
1
Das ist unrealted zu früh / spät Bindung (dynamische Typisierung vs. strukturellen typig - in Ihrem Beispiel werden die Methodenaufrufe überprüfen bei compiletime aber nicht unbedingt geschickt ). @Vidar: Das stimmt, aber es verzaubert dynamische Funktionen. Sie können auch Python kompilieren.
@Vidar: Es handelt sich nicht um ein kompiliertes oder interpretiertes Problem, sondern um ein statisches oder dynamisches Problem. In statischen OOP-Sprachen wie Java überprüft der Compiler, ob eine Klasse während der Kompilierungsphase eine Methode definiert. In einer dynamisch typisierten Sprache wie Objective-C werden Nachrichten zur Laufzeit übergeben.
mipadi
-1

Nachrichten werden entweder vom Kernel oder von der Sprache selbst verarbeitet (für ObjC gibt es beispielsweise einen sehr kleinen Assembler-Code, der dies erledigt).

Im Linux-Kernel werden Nachrichten beispielsweise mit Systemaufrufen / function erstellt: Sie können sie finden, wenn Sie nach Unix-Systemprogrammierung suchen.

Der Hauptunterschied zwischen einem Methodenaufruf und einer Nachricht ist folgender:

  • Ein Methodenaufruf tritt nur in Ihrem Code auf: In ASM wird er durch ein PUSH der übergebenen Argumente übersetzt.

  • Eine Kernel-Nachricht ist meistens etwas, das an den Kernel gesendet wird, der verfolgt und an einen bestimmten Prozess zurückgesendet wird. Ich verwechsle sie vielleicht mit Pipes, aber wie auch immer: Wissen Sie, dass es bereits Mechanismen gibt, mit denen Sie mehrere Programme gleichzeitig ausführen und gleichzeitig kommunizieren lassen können. Hoffen Sie natürlich nicht, dass dies unter Windows oder anderen Betriebssystemen genauso funktioniert.

jokoon
quelle
Dies ist keine "Nachrichtenübergabe", da dies für Programmiersprachen gilt.
mipadi