El paso de mensajes es una forma diferente de manejar la necesidad en el código OO de que un objeto obtenga otro objeto (o potencialmente él mismo) para hacer algo.
En la mayoría de los lenguajes modernos que descienden del enfoque de C ++, lo hacemos con llamadas a métodos. En este caso, el objeto llamado (a través de su definición de clase) pone una gran lista de las llamadas a los métodos que acepta y luego el codificador del objeto que llama simplemente escribe la llamada:
public void doSomething ( String input )
...
other_object.dosomething ( local )
Para lenguajes tipados estáticamente, el compilador puede verificar el tipo de cosa que se llama y confirmar que el método ha sido declarado. Para lenguajes escritos dinámicamente, eso se lleva a cabo en tiempo de ejecución.
Pero, en esencia, lo que sucede es que se envía un paquete de variables a un bloque de código específico.
Paso de mensajes
En los lenguajes de paso de mensajes (como el Objetivo C) en lugar de los métodos hay receptores, pero en general el enfoque de definirlos y llamarlos es muy similar: la diferencia es la forma en que se maneja.
En un lenguaje de mensaje pasado, el compilador puede verificar que el receptor al que ha llamado existe, pero en el peor de los casos, aparecerá una advertencia para decir que no está seguro de que esté allí. Esto se debe a que en el tiempo de ejecución lo que sucederá es que se llamará un bloque de código en el objeto receptor pasando tanto el paquete de variables como la firma del receptor al que desea llamar. Ese bloque de código luego busca el receptor y lo llama. Sin embargo, si el receptor no existe, el código simplemente devolverá un valor predeterminado.
Como resultado, una de las rarezas encontradas al pasar de C ++ / Java -> Objetivo C es comprender que puede "llamar a un método" en un objeto que no fue declarado en el tipo de tiempo de compilación, y que ni siquiera existía en el tipo de tiempo de ejecución ... y que la llamada no generaría una excepción sino que, de hecho, se devolvería un resultado.
Las ventajas de este enfoque son que aplana la jerarquía de la subclase y evita la mayoría de las necesidades de interfaces / herencia múltiple / tipos de pato. También permite que los objetos definan el comportamiento predeterminado cuando se les pide que hagan algo para lo que no tienen un receptor (comúnmente "si no lo hago, reenvío la solicitud a este otro objeto"). También puede simplificar la vinculación a las devoluciones de llamada (por ejemplo, para elementos de la interfaz de usuario y eventos cronometrados) particularmente sobre lenguajes tipados estáticamente como Java (para que pueda hacer que el botón llame al receptor "runTest" en lugar de llamar al método "actionPerformed" en la clase interna "RunTestButtonListener", que hace la llamada por usted).
Sin embargo, parece ser a costa de la necesidad de una verificación adicional por parte del desarrollador de que la llamada que creen que están haciendo está en el objeto correcto con el tipo correcto y pasando los parámetros correctos en el orden correcto, porque el compilador podría no advierte y se ejecutará perfectamente bien en tiempo de ejecución (solo devuelve una respuesta predeterminada). También podría decirse que hay un éxito en el rendimiento de la búsqueda adicional y el paso de parámetros.
En estos días, los lenguajes escritos dinámicamente pueden dar muchos de los beneficios del mensaje pasado OO con menos problemas.