He estado estudiando programación OO, principalmente en C ++, C # y Java. Pensé que lo entendía bien con mi comprensión de la encapsulación, la herencia y el polimorfismo (además de leer muchas preguntas en este sitio).
Una cosa que parece aparecer aquí y allá es el concepto de "pasar mensajes". Aparentemente, esto es algo que no se usa durante la programación OO en los idiomas principales de hoy en día, pero es compatible con Smalltalk.
Mis preguntas son:
- ¿Qué es el mensaje que pasa? (¿Alguien puede dar un ejemplo práctico?)
- ¿Hay algún soporte para este "paso de mensajes" en C ++, C # o Java?
java
c#
c++
object-oriented
Tom
fuente
fuente
Respuestas:
La transmisión de mensajes simplemente significa que (en un nivel muy abstracto) el mecanismo fundamental de la ejecución del programa son los objetos que se envían mensajes entre sí. El punto importante es que el nombre y la estructura de estos mensajes no están necesariamente fijos de antemano en el código fuente y pueden ser información adicional. Esta es una parte importante de lo que Alan Kay imaginó originalmente como "programación orientada a objetos".
Este lenguaje implementa una versión limitada del mensaje que pasa a través de llamadas a métodos. Limitado porque el conjunto de mensajes que se pueden enviar está limitado a los métodos declarados en una clase. La ventaja de este enfoque es que se puede implementar de manera muy eficiente y permite un análisis de código estático muy detallado (lo que resulta en todo tipo de beneficios útiles, como la finalización del código).
Por el contrario, los lenguajes que implican el paso de mensajes "reales" a menudo también tienen definiciones de métodos, como una forma conveniente de implementar manejadores de mensajes, pero permiten que las clases implementen manejadores de mensajes más flexibles que permiten al objeto recibir "llamadas a métodos" con nombres arbitrarios (no fijo en tiempo de compilación).
Un ejemplo en Groovy que demuestra el poder de este concepto:
producirá este XML:
Tenga en cuenta que
records
,car
,country
yrecord
son sintácticamente las llamadas de método, pero no existen métodos de ese nombre definido enMarkupBuilder
. En cambio, tiene un controlador de mensajes general que acepta todos los mensajes e interpreta los nombres de los mensajes como el nombre de un elemento XML, los parámetros como atributos y los cierres como elementos secundarios.fuente
sendMessage(property_name, Array of arguments)
ygetMessage(property_name, Array of arguments)
estático?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:
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.
fuente
Las arquitecturas de paso de mensajes son simplemente sistemas en los que cada componente es independiente de los demás, con un mecanismo común para pasar datos entre ellos. Puede considerar las llamadas a métodos como una forma de pasar mensajes, pero no es práctico hacerlo, confunde el problema. Esto se debe a que si tiene una clase con métodos bien definidos, y algún código que llama a esos métodos, todo se debe compilar, acoplando así el código y el objeto. puede ver cómo está cerca (cuando se pasa un mensaje y el compilador impone la corrección, pero pierde gran parte de la flexibilidad de un sistema desacoplado).
Las arquitecturas de paso de mensajes a menudo permiten agregar objetos en tiempo de ejecución, y la mayoría de las veces permiten que los mensajes se redirijan a uno o más objetos. Por lo tanto, puedo tener un código que transmita un mensaje de 'datos x actualizados' a todos los objetos que se han cargado en el sistema, y cada uno de ellos puede tomar las medidas que desee con esa información.
Un extraño ejemplo es la web. HTTP es un sistema de paso de mensajes: pasa un verbo de comando y un 'paquete de datos' a un proceso del servidor. (p. ej. GET http: \ myserver \ url) Ni a su navegador ni al servidor web le importan los datos que envía, ni a dónde los envía. El servidor lo pasará al código que empaquetará otro 'paquete' de datos y se lo enviará de vuelta. Ninguno de los componentes de este sistema sabe nada sobre el trabajo de los demás o lo que hacen, solo conocen el protocolo utilizado para la comunicación del mensaje.
fuente