Подтвердить что ты не робот

В чем разница между передачей сообщений и вызовом метода?

Есть ли разница между передачей сообщений и вызовом метода, или они могут считаться эквивалентными? Это, вероятно, характерно для языка; многие языки не поддерживают передачу сообщений (хотя все те, которые я могу придумать для методов поддержки), и те, которые могут иметь совершенно разные реализации. Кроме того, существуют большие различия в вызове метода в зависимости от языка (C против Java vs Lisp по сравнению с вашим любимым языком). Я считаю, что это язык-агностик. Что вы можете сделать с помощью метода-метода, который вы не можете сделать с помощью метода invoked, и наоборот (на вашем любимом языке)?

4b9b3361

Ответ 1

в первом приближении, ответ: none, если вы "ведете себя нормально"

Несмотря на то, что многие думают, что есть - технически, это обычно одно и то же: кэшированный поиск части кода, который должен быть выполнен для конкретной именованной операции (по крайней мере, для обычного случая). Вызов имени операции "сообщение" или "виртуальный метод" не имеет значения.

НО: язык актера действительно отличается: наличие активных объектов (у каждого объекта есть неявная очередь сообщений и рабочий поток - по крайней мере, концептуально), параллельная обработка becones проще в обращении (google также "сообщает последовательные процессы" для больше).

НО: в Smalltalk можно обернуть объекты, чтобы сделать их актоподобными, без фактического изменения компилятора, синтаксиса или даже перекомпиляции.

НО: в Smalltalk, когда вы пытаетесь отправить сообщение, которое не подделывается получателем (т.е. "someObject foo: arg" ), создается объект сообщения, содержащий имя и аргументы, объект передается как аргумент сообщения "doesNotUnderstand". Таким образом, объект может решить, как справляться с нереализованными сообщениями-отправлениями (иначе называемыми нереализованными методами). Конечно, это может привести их в очередь для рабочего процесса, чтобы упорядочить их...

Конечно, это невозможно со статически типизированными языками (если вы не очень сильно используете отражение), но на самом деле ОЧЕНЬ полезная функция. Объекты прокси, загрузка кода по требованию, удаленные вызовы процедур, учебный и самомодифицирующий код, адаптирующие и самооптимизирующиеся программы, обертки corba и dcom, рабочие очереди построены на этой схеме. Это может быть неправильно использовано и привести к ошибкам во время выполнения - конечно. Так что это двухсторонний меч. Острый и мощный, но опасный в руке новичков...

EDIT: Я пишу о реализации языка здесь (как в Java против Smalltalk, а не о механизмах межпроцессного взаимодействия.

Ответ 2

IIRC, они были официально доказаны как эквивалентные. Не нужно много думать, чтобы хотя бы указать, что они должны быть. Все, что требуется, это на мгновение игнорировать прямую эквивалентность вызываемого адреса с фактическим пятном в памяти и рассматривать его просто как число. С этой точки зрения число является просто абстрактным идентификатором, который однозначно идентифицирует конкретный тип функциональности, которую вы хотите вызвать.

Даже когда вы вызываете функции на одном компьютере, нет реального требования, чтобы вызываемый адрес указывал физический (или даже виртуальный) адрес вызываемой функции. Например, хотя почти никто никогда их не использует, защитные режимы в режиме защищенного режима позволяют сделать вызов непосредственно непосредственно в главном окне задачи. В этом случае только сегментная часть адреса обрабатывается как фактический адрес, то есть любой вызов сегмента затвора задачи заканчивается вызовом того же адреса, независимо от указанного смещения. Если это необходимо, код обработки может проверять указанное смещение и использовать его для принятия решения о вызове отдельного метода, но связь между указанным смещением и адресом вызываемой функции может быть полностью произвольной.

Вызов функции-члена - это просто тип передачи сообщений, который обеспечивает (или, по крайней мере, облегчает) оптимизацию под общим обстоятельством, что клиент и сервер службы, о которой идет речь, имеют общее адресное пространство. Соответствие 1:1 между абстрактным идентификатором службы и адресом, в котором находится поставщик этой службы, позволяет тривиальным, исключительно быстрому отображению от одного к другому.

В то же время не ошибитесь в этом: тот факт, что что-то похоже на вызов функции-члена, не мешает ему фактически выполняться на другой машине или асинхронно или (часто) и то, и другое. Типичным механизмом для этого является прокси-функция, которая переводит "виртуальное сообщение" вызова функции-члена в "реальное сообщение", которое может (например) передаваться по сети по мере необходимости (например, Microsoft DCOM и CORBA оба делают это довольно регулярно).

Ответ 3

Используя 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 компилятор просто выдает вам предупреждение о передаче сообщения объекту, который, по его мнению, объект может не понимать, но игнорирование его не останавливает выполнение вашей программы.

В то время как это очень мощное и гибкое, это может привести к труднодоступным ошибкам при неправильном использовании из-за повреждения стека.

Адаптировано из статьи здесь. Также см. эту статью для получения дополнительной информации.

Ответ 4

На самом деле это не то же самое на практике. Передача сообщений - способ передачи данных и инструкций между двумя или более параллельными процессами. Вызов метода - способ вызова подпрограммы. Erlang concurrency построен на прежней концепции с его параллельным ориентированным программированием.

Передача сообщений, скорее всего, связана с формой вызова метода, но вызов метода необязательно связан с передачей сообщений. Если бы это было сделано, это было бы передачей сообщений. Передача сообщений - это одна из форм синхронизации между параллельными процессами. Вызов метода обычно означает синхронные действия. Вызывающий абонент ждет завершения метода до его продолжения. Передача сообщений - это форма сопрограммы. Метод-вызов - это форма подпрограммы.

Все подпрограммы являются сопрограммами, но все сопрограммы не являются подпрограммами.

Ответ 5

Есть ли разница между передачей сообщений и вызовом метода, или они могут считаться эквивалентными?

Они похожи. Некоторые отличия:

Сообщения могут передаваться синхронно или асинхронно (например, разница между SendMessage и PostMessage в Windows)

Вы можете отправить сообщение, не зная, какой удаленный объект вы его отправляете в

Целевой объект может находиться на удаленном компьютере или O/S.