Przekazywanie wiadomości to inny sposób radzenia sobie z potrzebą w kodzie OO, aby jeden obiekt uzyskał inny obiekt (lub potencjalnie sam) do zrobienia czegoś.
W większości współczesnych języków wywodzących się z podejścia C ++ robimy to za pomocą wywołań metod. W tym przypadku wywoływany obiekt (poprzez swoją definicję klasy) umieszcza dużą listę akceptowanych wywołań metod, a następnie koder obiektu wywołującego po prostu zapisuje wywołanie:
public void doSomething ( String input )
...
other_object.dosomething ( local )
W przypadku języków o typie statycznym kompilator może następnie sprawdzić typ wywoływanej rzeczy i potwierdzić, że metoda została zadeklarowana. W przypadku języków dynamicznie wpisywanych odbywa się to w czasie wykonywania.
Ale w gruncie rzeczy dzieje się tak, że pakiet zmiennych jest wysyłany do określonego bloku kodu.
Przekazywanie wiadomości
W językach przekazujących wiadomości (takich jak Cel C) zamiast metod istnieją odbiorniki, ale ogólnie podejście do ich definiowania i wywoływania jest takie samo - różnica polega na sposobie, w jaki jest obsługiwany.
W przekazywanym języku kompilator może sprawdzić, czy odbiornik, do którego zadzwoniłeś, istnieje, ale w najgorszym przypadku wyświetli ostrzeżenie, że nie jest pewien, czy tam jest. Wynika to z faktu, że w czasie wykonywania nastąpi wywołanie bloku kodu na obiekcie odbierającym, przekazując zarówno pakiet zmiennych, jak i podpis odbiorcy, który chcesz wywołać. Ten blok kodu następnie szuka odbiornika i wywołuje go. Jeśli jednak odbiornik nie istnieje, kod po prostu zwróci wartość domyślną.
W rezultacie jedną z osobliwości stwierdzonych podczas przechodzenia z C ++ / Java -> Cel C jest zrozumienie, że można „wywołać metodę” na obiekcie, który nie został zadeklarowany w typie czasu kompilacji, a nawet nie istniał typ wykonania ... i że wywołanie nie spowodowałoby wyrzucenia wyjątku, ale w rzeczywistości wynik zostałby przekazany z powrotem.
Zaletami tego podejścia jest to, że spłaszcza hierarchię podklasy i pozwala uniknąć większości potrzeb związanych z interfejsami / wielokrotnym dziedziczeniem / typami kaczek. Pozwala także obiektom zdefiniować domyślne zachowanie, gdy zostanie poproszony o zrobienie czegoś, dla czego nie ma odbiornika (zwykle „jeśli tego nie zrobię, przekaż żądanie do tego innego obiektu”). Może także uprościć łączenie z wywołaniami zwrotnymi (np. Dla elementów interfejsu użytkownika i zdarzeń czasowych), szczególnie w przypadku języków o typie statycznym, takich jak Java (dzięki czemu przycisk może wywoływać odbiornik „runTest” zamiast wywoływać metodę „actionPerformed” w klasie wewnętrznej „RunTestButtonListener”, który wykonuje wywołanie dla Ciebie).
Wydaje się jednak, że kosztem jest dodatkowe sprawdzenie przez dewelopera, czy wywołanie, które według nich wykonują, znajduje się na właściwym obiekcie z odpowiednim typem i przekazuje odpowiednie parametry we właściwej kolejności, ponieważ kompilator może nie ostrzeże cię, a będzie działał idealnie dobrze w czasie wykonywania (po prostu zwraca domyślną odpowiedź). Można również przypuszczać, że poprawiono wydajność dzięki dodatkowemu spojrzeniu i przekazywaniu parametrów.
Obecnie dynamicznie pisane języki mogą dawać wiele korzyści z OO przekazywanych z mniejszą ilością problemów.