Відмінності між повідомленнями та методами?


13

У Objective C у вас є концепція надсилання повідомлень іншим об'єктам, і це дуже схоже на метод виклику на таких мовах, як C # та Java.

Але які саме тонкі відмінності? Як я повинен думати про обмін повідомленнями, коли думає про свій код?

Примітка. Тут я лише трохи передумов, я розробник C # / Java, який намагається зрозуміти деякі поняття щодо Цілі C.


2
Оскільки вони всі різні мови, відмінності не є тонкими. Вони різні мови. "коли думаєте про мій код"? Який код? Думаючи про Java або C #, ви не думаєте про повідомлення. Ви думаєте про методи. Чи можете ви уточнити, як неспоріднені мови з непов'язаними поняттями можуть мати «тонкі» відмінності?
S.Lott

1
Задайте питання на сайті stackoverflow.com
Амір Резай

1
Чи справді це питання має бути на StackOverflow? Це питання щодо понять програмування, а не проблема щодо якогось коду, який я отримав. Можливо, я помиляюся, я не знаю - межі розмиваються ...
Vidar

1
@Vidar, питання не суб'єктивне. Ви шукаєте визначення підручника. Програмісти більше для думок, досвіду та суб'єктивних питань.
Стівен Фурлані

1
Гаразд - чи є спосіб змусити модератора перенести це питання на StackOverflow?
Відар

Відповіді:


10

Повідомлення - це ім'я селектора та параметри цього селектора.

Селектор - символ.

Метод - це фрагмент коду в класі, ідентифікований селектором.

Іншими словами, [foo bar: baz]говорить "надіслати повідомлення, викликане @selector(bar:)параметром, bazна об'єкт foo. Ви можете надіслати це повідомлення багатьом різним об'єктам.

На противагу цьому може бути такий метод bar: для Fooсили

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

але для FooTwoсили може виглядати так

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

(Я сподіваюся, що я маю право на синтаксис; минуло певний час, коли я останній раз торкнувся Objective-C.)

Коли ви надсилаєте повідомлення, ядро ​​Objective-C посилає повідомлення, fooяке вирішує, чи розуміє воно повідомлення. Він вирішує це на основі того, чи може він знайти метод, визначений цим селектором.

Два методи з однаковою назвою та одне повідомлення.

Також об'єкт може просто переслати певне повідомлення (або набір повідомлень) іншому об'єкту для обробки. У цьому випадку ви надсилаєте повідомлення цьому проксі-об'єкту, який не має методів відповідності цьому повідомленню , і проксі-сервер пересилає повідомлення його обгорнутому об'єкту.


тож ... повідомлення, коли ви викликаєте роз'єднаний інтерфейс (селектор a.invoke, args), а метод - це коли ви викликаєте інтерфейс (a.methodName)? Хіба це не зробить Java, JavaScript, усі динамічні мови мають повідомлення, тому що все відбувається через подвійний інтерфейс, а не прямі стрибки та зміщення у вінтабельні стрибки)?
Дмитро

4

З чисто теоретичної точки зору, різниці між ними взагалі немає - існував ряд формальних доказів, що свідчать про те, що вони цілком рівноцінні, і будь-які можуть бути реалізовані повністю з точки зору іншого.

З трохи менш теоретичного погляду існує одна можлива різниця: у типовій реалізації віртуальна таблиця функцій статично розподіляється і вміст кожного vtable фіксується під час компіляції. Пошук повідомлень, навпаки, зазвичай виконується з якимось об’єктом, подібним до карти, який, як правило, динамічний, тобто ви можете змінювати його під час виконання. Це дозволяє порівняно легко додати нову відповідь до повідомлення в існуючий клас. На жаль, у більшості випадків це залишається здебільшого теоретичним. По-перше, ви в основному маєте справу з кодом, що самозмінюється, який, як вважає більшість людей, довго був досить поганою ідеєючас тому. По-друге, щоб зробити це дуже значимим, вам, як правило, потрібно вміти складати новий код у існуючий клас, щоб відповісти на нове повідомлення, яке ви підтримуєте. Без цього майже все, що ви отримуєте, - це можливість динамічно додавати нове ім'я до існуючого методу.

Як випливає з кінця попереднього пункту, з по-справжньому практичної точки зору, різниця між ними взагалі дуже мала. Вони просто два (дуже трохи) різні способи підтримки пізнього зв'язування. Хоча пошук на основі повідомлень, як правило, трохи повільніше, було б досить незвично, щоб різниця була справді значною. Для більшості практичних цілей це лише два різні способи досягнення однієї і тієї ж речі.


3
Чи є у вас посилання на докази? Я хотів би поглянути. Існує велика різниця між викликом методу Java і надсиланням повідомлень Smalltalk не тільки через пізнє прив'язування, але і через роз'єднання відправника та одержувача: ви не можете сказати, чи отримувач повідомлення обробляє його, чи пересилає повідомлення наприклад, наприклад.
Френк Ширар

@FrankShearar: Вибачте, але ні. Докази, які я бачив, були надруковані, і давно, коли ООП та методи його здійснення були досить новими, що докази про такі речі були цікаві вченим.
Джеррі Труну

1

У Objective-C повідомлення є пізньообмеженими. Тобто вони вирішуються під час виконання. C # підтримує аналогічну конструкцію за допомогою ключового слова Dynamic, яке також оголошує об'єкт як пізно обмеженим.


0

Зазвичай виклики методів вирішуються під час компіляції (якщо ви не використовуєте відображення в Java), тоді як повідомлення в Цілі C надсилаються під час виконання.


2
Якщо виклики методів вирішено, це час компіляції, ви не використовуєте OOP, ви використовуєте синтаксичний цукор для перевантажених функцій, приймаючи structяк перший параметр. Пізній біндунг є важливою частиною поліморфізму і, отже, ООП.

2
Так. Але все ж ви можете кодувати лише виклик методу проти чогось (на Java), який добре відомий під час компіляції. Виклик MyObject.foo () призведе до помилки, якщо для MyObject або MyInterface не визначено методу foo (). ObjC дозволить надіслати вам повідомлення "foo", щоб заперечити MyObject - і якщо в MyObject немає "foo", це буде бомбити під час виконання.
Хайко Рупп

Я думав, що ціль C - це складена мова?
Vidar

1
Це нереально для раннього / пізнього прив'язування (динамічне введення тексту та структурний шрифт - у вашому прикладі виклики методів перевіряються під час компіляції, але не обов'язково розсилаються ). @Vidar: Так, але додає магії динамічним особливостям. Ви також можете компілювати Python.

@Vidar: Це не питання компільованого проти інтерпретованого, а швидше статичного проти динамічного. У статичних мовах OOP, як Java, компілятор перевіряє, чи клас визначає метод під час фази компіляції. На динамічно типізованій мові, як Objective-C, повідомлення передаються під час виконання.
mipadi

-1

Повідомлення обробляються ядром або самою мовою (наприклад, для ObjC, є дуже малий код складання, який це робить).

Наприклад, в ядрі Linux, повідомлення виконуються із системними викликами / функцією: про них можна знайти, якщо шукати програмне забезпечення Unix.

Основна різниця між викликом методу та повідомленням полягає в наступному:

  • виклик методу відбувається лише у вашому коді: у ASM він перекладається PUSH переданих аргументів.

  • повідомлення ядра - це здебільшого те, що надсилається до ядра, яке відстежується та відправляється назад до певних процесів. Я можу помилитися з ними за труби, але що завгодно: знайте, вже є механізми, які дозволяють запускати кілька програм одночасно і дозволяти спілкуватися одночасно. Звичайно, не сподівайтеся, що це буде працювати так само, як у Windows чи інших ОС.


Це не "передача повідомлення", як це стосується мов програмування.
mipadi
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.