消息传递和方法调用有什么区别?

发布于 2024-09-16 01:03:10 字数 195 浏览 8 评论 0原文

消息传递和方法调用之间有区别吗?或者它们可以被认为是等效的吗?这可能是特定于该语言的;许多语言不支持消息传递(尽管我能想到的所有语言都支持方法),而支持消息传递的语言可以有完全不同的实现。此外,根据语言的不同,方法调用也存在很大差异(C、Java、Lisp、您最喜欢的语言)。我相信这是与语言无关的。你可以用传递方法做什么而用调用方法不能做什么,反之亦然(用你最喜欢的语言)?

Is there a difference between message-passing and method-invocation, or can they be considered equivalent? This is probably specific to the language; many languages don't support message-passing (though all the ones I can think of support methods) and the ones that do can have entirely different implementations. Also, there are big differences in method-invocation depending on the language (C vs. Java vs Lisp vs your favorite language). I believe this is language-agnostic. What can you do with a passed-method that you can't do with an invoked-method, and vice-versa (in your favorite language)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

日记撕了你也走了 2024-09-23 01:03:10

使用 Objective-C 作为消息示例,使用 Java 作为方法示例,主要区别在于,当传递消息时,对象决定如何处理该消息(通常会导致调用对象中的实例方法)。

然而,在 Java 中,方法调用是一个更加静态的事情,因为您必须拥有对调用该方法的类型的对象的引用,并且该类型中必须存在具有相同名称和类型签名的方法,否则编译器将会抱怨。有趣的是实际的调用是动态的,尽管这对程序员来说并不明显。

例如,考虑像

class MyClass {
    void doSomething() {}
}

class AnotherClass {
    void someMethod() {
        Object object = new Object();
        object.doSomething(); // compiler checks and complains that Object contains no such method.

        // However, through an explicit cast, you can calm the compiler down,
        // even though your program will crash at runtime
        ((MyClass) object).doSomething(); // syntactically valid, yet incorrect
    }
}

Objective-C 这样的类,但是,编译器只是向您发出警告,将其认为对象可能无法理解的消息传递给对象,但忽略它并不会阻止您的程序执行。

虽然它非常强大且灵活,但如果使用不当,可能会因堆栈损坏而导致难以发现的错误。

改编自此处的文章。
另请参阅这篇文章了解更多信息。

Using Objective-C as an example of messages and Java for methods, the major difference is that when you pass messages, the Object decides how it wants to handle that message (usually results in an instance method in the Object being called).

In Java however, method invocation is a more static thing, because you must have a reference to an Object of the type you are calling the method on, and a method with the same name and type signature must exist in that type, or the compiler will complain. What is interesting is the actual call is dynamic, although this is not obvious to the programmer.

For example, consider a class such as

class MyClass {
    void doSomething() {}
}

class AnotherClass {
    void someMethod() {
        Object object = new Object();
        object.doSomething(); // compiler checks and complains that Object contains no such method.

        // However, through an explicit cast, you can calm the compiler down,
        // even though your program will crash at runtime
        ((MyClass) object).doSomething(); // syntactically valid, yet incorrect
    }
}

In Objective-C however, the compiler simply issues you a warning for passing a message to an Object that it thinks the Object may not understand, but ignoring it doesn't stop your program from executing.

While this is very powerful and flexible, it can result in hard-to-find bugs when used incorrectly because of stack corruption.

Adapted from the article here.
Also see this article for more information.

骑趴 2024-09-23 01:03:10

作为第一个近似值,答案是:没有,只要你“表现正常”

尽管很多人认为有 - 从技术上讲,它通常是相同的:对要为特定命名执行的一段代码进行缓存查找- 操作(至少对于正常情况)。将操作的名称称为“消息”或“虚拟方法”并没有什么区别。

但是:Actor 语言确实不同:在拥有活动对象时(每个对象都有一个隐式消息队列和一个工作线程 - 至少在概念上),并行处理变得更容易处理(谷歌还“通信顺序进程”以获取更多信息)。

但是:在 Smalltalk 中,可以包装对象以使它们像 actor 一样,而无需实际更改编译器、语法甚至重新编译。

但是:在 Smalltalk 中,当您尝试发送接收者无法理解的消息(即“someObject foo:arg”)时,会创建一个消息对象,其中包含名称和参数,并且该消息对象会被传递作为“doesNotUnderstand”消息的参数。因此,对象可以自行决定如何处理未实现的消息发送(也称为未实现的方法的调用)。当然,它可以将它们推入队列,以便工作进程对它们进行排序...

当然,这对于静态类型语言来说是不可能的(除非您大量使用反射),但实际上这是一个非常有用的功能。代理对象、按需加载代码、远程过程调用、学习和自我修改代码、适应和自我优化程序、corba 和 dcom 包装器、工作队列都建立在该方案之上。当然,它可能会被滥用,并导致运行时错误。
所以它是一把双面剑。锋利而强大,但对于初学者来说很危险......

编辑:我在这里写的是关于语言实现的文章(如 Java 与 Smalltalk 中的比较 - 而不是进程间机制。

as a first approximation, the answer is: none, as long as you "behave normally"

Even though many people think there is - technically, it is usually the same: a cached lookup of a piece of code to be executed for a particular named-operation (at least for the normal case). Calling the name of the operation a "message" or a "virtual-method" does not make a difference.

BUT: the Actor language is really different: in having active objects (every object has an implicit message-queue and a worker thread - at least conceptionally), parallel processing becones easier to handle (google also "communicating sequential processes" for more).

BUT: in Smalltalk, it is possible to wrap objects to make them actor-like, without actually changing the compiler, the syntax or even recompiling.

BUT: in Smalltalk, when you try to send a message which is not understoof by the receiver (i.e. "someObject foo:arg"), a message-object is created, containing the name and the arguments, and that message-object is passed as argument to the "doesNotUnderstand" message. Thus, an object can decide itself how to deal with unimplemented message-sends (aka calls of an unimplemented method). It can - of course - push them into a queue for a worker process to sequentialize them...

Of course, this is impossible with statically typed languages (unless you make very heavy use of reflection), but is actually a VERY useful feature. Proxy objects, code load on demand, remote procedure calls, learning and self-modifying code, adapting and self-optimizing programs, corba and dcom wrappers, worker queues are all built upon that scheme. It can be misused, and lead to runtime bugs - of course.
So it it is a two-sided sword. Sharp and powerful, but dangerous in the hand of beginners...

EDIT: I am writing about language implementations here (as in Java vs. Smalltalk - not inter-process mechanisms.

×眷恋的温暖 2024-09-23 01:03:10

IIRC,它们已被正式证明是等效的。不需要太多的思考,至少表明它们应该如此。所需要的只是暂时忽略被调用地址与内存中实际位置的直接等价性,并将其简单地视为一个数字。从这个角度来看,数字只是一个抽象标识符,它唯一地标识您希望调用的特定类型的功能。

即使当您在同一台机器中调用函数时,也没有实际要求被调用地址直接指定被调用函数的物理(甚至虚拟)地址。例如,尽管几乎没有人真正使用它们,但英特尔保护模式任务门允许直接调用任务门本身。在这种情况下,只有地址的段部分被视为实际地址——即,对任务门段的任何调用最终都会调用相同的地址,而不管指定的偏移量如何。如果需要,处理代码可以检查指定的偏移量,并使用它来决定要调用的单个方法 - 但指定的偏移量和调用函数的地址之间的关系可以是完全任意的。

成员函数调用只是一种消息传递类型,它在所讨论的服务的客户端和服务器共享公共地址空间的常见情况下提供(或至少促进)优化。抽象服务标识符和该服务提供者所在的地址之间的 1:1 对应关系允许从一个到另一个的简单且异常快速的映射。

同时,请不要误会:某些东西看起来类似于成员函数调用,这一事实并不妨碍它在另一台机器上实际执行或异步执行,或(经常)两者兼而有之。实现这一点的典型机制是代理函数,它将成员函数调用的“虚拟消息”转换为“真实消息”,该消息可以(例如)根据需要通过网络传输(例如,Microsoft 的 DCOM 和 CORBA 都可以)这很常见)。

IIRC, they've been formally proven to be equivalent. It doesn't take a whole lot of thinking to at least indicate that they should be. About all it takes is ignoring, for a moment, the direct equivalence of the called address with an actual spot in memory, and consider it simply as a number. From this viewpoint, the number is simply an abstract identifier that uniquely identifies a particular type of functionality you wish to invoke.

Even when you are invoking functions in the same machine, there's no real requirement that the called address directly specify the physical (or even virtual) address of the called function. For example, although almost nobody ever really uses them, Intel protected mode task gates allow a call to be made directly to the task gate itself. In this case, only the segment part of the address is treated as an actual address -- i.e., any call to a task gate segment ends up invoking the same address, regardless of the specified offset. If so desired, the processing code can examine the specified offset, and use it to decide upon an individual method to be invoked -- but the relationship between the specified offset and the address of the invoked function can be entirely arbitrary.

A member function call is simply a type of message passing that provides (or at least facilitates) an optimization under the common circumstance that the client and server of the service in question share a common address space. The 1:1 correspondence between the abstract service identifier and the address at which the provider of that service reside allows a trivial, exceptionally fast, mapping from one to the other.

At the same time, make no mistake about it: the fact that something looks like a member function call doesn't prevent it from actually executing on another machine or asynchronously, or (frequently) both. The typical mechanism to accomplish this is proxy function that translates the "virtual message" of a member function call into a "real message" that can (for example) be transmitted over a network as needed (e.g., Microsoft's DCOM, and CORBA both do this quite routinely).

行雁书 2024-09-23 01:03:10

在实践中它们确实不是一回事。消息传递是在两个或多个并行进程之间传输数据和指令的一种方式。方法调用是调用子例程的一种方法。 Erlang 的并发性是建立在前一个概念及其面向并发编程的基础上的。

消息传递很可能涉及某种形式的方法调用,但方法调用不一定涉及消息传递。如果确实如此,那就是消息传递。消息传递是在并行进程之间执行同步的一种形式。方法调用通常意味着同步活动。调用者等待方法完成才能继续。消息传递是协程的一种形式。方法调用是子例程的一种形式。

所有子例程都是协程,但所有协程都不是子例程。

They really aren't the same thing in practice. Message passing is a way to transfer data and instructions between two or more parallel processes. Method invocation is a way to call a subroutine. Erlang's concurrency is built on the former concept with its Concurrent Oriented Programing.

Message passing most likely involves a form of method invocation, but method invocation doesn't necessarily involve message passing. If it did it would be message passing. Message passing is one form of performing synchronization between to parallel processes. Method invocation generally means synchronous activities. The caller waits for the method to finish before it can continue. Message passing is a form of a coroutine. Method-invocation is a form of subroutine.

All subroutines are coroutines, but all coroutines are not subroutines.

油饼 2024-09-23 01:03:10

消息传递和方法调用之间有区别吗?或者它们可以被视为等效吗?

他们很相似。一些区别:

消息可以同步或异步传递(例如 Windows 中 SendMessage 和 PostMessage 之间的区别)

您可能在不确切知道要发送到哪个远程对象的情况下发送消息

目标对象可能位于远程计算机或 O/ S。

Is there a difference between message-passing and method-invocation, or can they be considered equivalent?

They're similar. Some differences:

Messages can be passed synchronously or asynchronously (e.g. the difference between SendMessage and PostMessage in Windows)

You might send a message without knowing exactly which remote object you're sending it to

The target object might be on a remote machine or O/S.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文