Я изучал ОО-программирование, прежде всего на C ++, C # и Java. Я думал, что хорошо разбираюсь в этом с моим пониманием инкапсуляции, наследования и полиморфизма (а также прочитав много вопросов на этом сайте).
Одна вещь, которая, кажется, всплывает здесь и там, это понятие «передача сообщений». По-видимому, это то, что не используется при ОО-программировании в современных основных языках, но поддерживается Smalltalk.
Мои вопросы:
- Что такое передача сообщений? (Может кто-нибудь привести практический пример?)
- Есть ли поддержка этой «передачи сообщений» в C ++, C # или Java?
java
c#
c++
object-oriented
Том
источник
источник
Ответы:
Передача сообщений просто означает, что (на очень абстрактном уровне) основным механизмом выполнения программы являются объекты, отправляющие друг другу сообщения. Важным моментом является то, что имя и структура этих сообщений не обязательно заранее зафиксированы в исходном коде и могут сами по себе быть дополнительной информацией. Это важная часть того, что Алан Кей изначально представлял как «объектно-ориентированное программирование».
Эти языки реализуют ограниченную версию передачи сообщений через вызовы методов. Ограничено, потому что набор сообщений, которые могут быть отправлены, ограничен методами, объявленными в классе. Преимущество этого подхода состоит в том, что он может быть реализован очень эффективно, и он обеспечивает очень подробный статический анализ кода (который приводит ко всем видам полезных преимуществ, таких как завершение кода).
И наоборот, языки, которые обеспечивают «реальную» передачу сообщений, также часто имеют определения методов, что является удобным способом реализации обработчиков сообщений, но позволяет классам реализовывать более гибкие обработчики сообщений, которые позволяют объекту получать «вызовы методов» с произвольными именами (не исправлено). во время компиляции).
Пример в Groovy, который демонстрирует силу этой концепции:
создаст этот XML:
Следует отметить , что
records
,car
,country
иrecord
синтаксически вызовы методов, но нет методов этого имени , определенного вMarkupBuilder
. Вместо этого он имеет обработчик сообщений catchall, который принимает все сообщения и интерпретирует имена сообщений как имя элемента XML, параметры как атрибуты и замыкания как дочерние элементы.источник
sendMessage(property_name, Array of arguments)
иgetMessage(property_name, Array of arguments)
статических языках?Передача сообщений - это другой способ удовлетворения потребности в ОО-коде для того, чтобы один объект заставил другой объект (или, возможно, сам) что-то сделать.
В большинстве современных языков, которые происходят от подхода C ++, мы делаем это с помощью вызовов методов. В этом случае вызываемый объект (через определение класса) помещает большой список того, что вызывает метод, который он принимает, и затем кодировщик вызывающего объекта просто записывает вызов:
Для статически типизированных языков компилятор может затем проверить тип вызываемой вещи и подтвердить, что метод был объявлен. Для динамически типизированных языков это выполняется во время выполнения.
Но, по сути, происходит то, что пакет переменных отправляется в определенный блок кода.
Передача сообщений
В языках передачи сообщений (таких как Objective C) вместо методов есть приемники, но в целом подход определения и вызова их во многом аналогичен - различие заключается в способе его обработки.
На языке передаваемых сообщений компилятор может проверить, что получатель, который вы вызвали, существует, но в худшем случае он выдаст предупреждение о том, что он не уверен, что он там есть. Это происходит потому, что во время выполнения будет вызван блок кода на принимающем объекте, передающий как пакет переменных, так и сигнатуру получателя, которого вы хотите вызвать. Затем этот блок кода ищет получателя и вызывает его. Однако, если получатель не существует, тогда код просто вернет значение по умолчанию.
В результате одна из странностей, обнаруженных при переходе с C ++ / Java -> Objective C, заключается в понимании того, что вы можете «вызвать метод» для объекта, который не был объявлен в типе времени компиляции и даже не существует в тип времени выполнения ... и что вызов не будет вызывать исключение, а фактически будет возвращать результат.
Преимущества этого подхода состоят в том, что он выравнивает иерархию подкласса и устраняет большинство потребностей в интерфейсах / множественном наследовании / типах утки. Он также позволяет объектам определять поведение по умолчанию, когда их просят сделать что-то, для чего у них нет получателя (обычно «если я этого не делаю, перенаправьте запрос этому другому объекту»). Это также может упростить привязку к обратным вызовам (например, для элементов пользовательского интерфейса и синхронизированных событий), особенно в статически типизированных языках, таких как Java (так что вы можете заставить кнопку вызывать получатель «runTest», а не вызывать метод «actionPerformed» для внутреннего класса). "RunTestButtonListener", который делает вызов для вас).
Однако может показаться, что за счет необходимости дополнительной проверки разработчиком, что вызов, который они совершают, находится на правильном объекте с правильным типом и передачей правильных параметров в правильном порядке, потому что компилятор может не предупреждаю вас, и он будет отлично работать во время выполнения (просто возвращая ответ по умолчанию). Также возможно снижение производительности от дополнительного просмотра и передачи параметров.
В наши дни языки с динамической типизацией могут дать много преимуществ ОО, передаваемых сообщениями, с меньшим количеством проблем.
источник
Архитектуры передачи сообщений - это просто системы, в которых каждый компонент независим от других, с общим механизмом передачи данных между ними. Вы можете рассматривать вызовы методов как форму передачи сообщений, но это непрактично - это запутывает проблему. Это потому, что если у вас есть класс с четко определенными методами и некоторый код, который вызывает эти методы, все это должно быть скомпилировано вместе, таким образом, связывая код и объект. Вы можете видеть, как оно близко (когда сообщение передается, и компилятор обеспечивает его корректность, но он теряет большую часть гибкости отсоединенной системы).
Архитектуры передачи сообщений часто позволяют добавлять объекты во время выполнения и чаще всего позволяют перенаправлять сообщения одному или нескольким объектам. Таким образом, у меня может быть некоторый код, который передает сообщение «данные х обновлены» всем объектам, которые были загружены в систему, и каждый из них может предпринять любое действие с этой информацией.
Странный пример - сеть. HTTP - это система передачи сообщений - вы передаете командный глагол и «пакет данных» процессу сервера. (например, GET http: \ myserver \ url) Ни ваш браузер, ни веб-сервер не заботятся ни о данных, которые вы отправляете, ни о том, куда вы их отправляете. Сервер передаст его в код, который упакует другой «пакет» данных и отправит его вам. Ни один из компонентов в этой системе ничего не знает о работе других или о том, что они делают, они просто знают протокол, используемый для передачи сообщений.
источник