¿Diferencias entre mensajes y métodos?

13

En Objective C tienes el concepto de enviar mensajes a otros objetos, y, bueno, esto es muy similar a llamar a métodos en lenguajes como C # y Java.

Pero, ¿cuáles son exactamente las diferencias sutiles? ¿Cómo debo pensar en los mensajes cuando pienso en mi código?

Nota: Solo un poco de experiencia aquí, soy un desarrollador de C # / Java que intenta entender algunos conceptos sobre Objective C.

Vidar
fuente
2
Como todos son idiomas diferentes, las diferencias no son sutiles. Son idiomas diferentes "cuando pienso en mi código"? ¿Qué código? Cuando piensa en Java o C #, no piensa en los mensajes. Piensas en los métodos. ¿Puede aclarar cómo los lenguajes no relacionados con conceptos no relacionados pueden tener diferencias "sutiles"?
S.Lott
1
Haga su pregunta en stackoverflow.com
Amir Rezaei
1
¿Debería esta pregunta realmente estar en StackOverflow? Es una pregunta sobre los conceptos de programación, no un problema sobre el código que tengo. Tal vez me equivoque, no sé - los límites se difuminan ...
Vidar
1
@Vidar, la pregunta no es subjetiva. Estás buscando una definición de libro de texto. Los programadores son más para opiniones, experiencia y preguntas subjetivas.
Stephen Furlani
1
OK, ¿hay alguna manera de hacer que el moderador mueva esta pregunta a StackOverflow?
Vidar

Respuestas:

10

Un mensaje es el nombre de un selector y los parámetros para ese selector.

Un selector es un símbolo.

Un método es un fragmento de código en una clase identificada por un selector.

En otras palabras, [foo bar: baz]dice "envíe el mensaje llamado @selector(bar:)con el parámetro bazal objeto foo. Puede enviar ese mensaje a muchos objetos diferentes.

Por el contrario, el método bar: para un Foopodría verse así

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

pero por un momento FooTwopodría parecer

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

(Espero tener la sintaxis correcta; ha pasado un tiempo desde la última vez que toqué Objective-C).

Cuando envía el mensaje, el núcleo Objective-C envía el mensaje al fooque decide si comprende el mensaje. Decide esto en función de si puede encontrar un método identificado por ese selector.

Dos métodos con el mismo nombre y un mensaje.

También es posible que un objeto simplemente reenvíe un mensaje particular (o conjunto de mensajes) a otro objeto para su procesamiento. En este caso, envía un mensaje a este objeto proxy, que no tiene métodos para que coincida con ese mensaje , y el proxy reenvía el mensaje a su objeto envuelto.

Frank Shearar
fuente
entonces ... ¿un mensaje es cuando llamas a una interfaz de usuario (a.invoke selector, args) y un método es cuando llamas a una interfaz (a.methodName)? ¿No haría eso java, JavaScript, todos los lenguajes dinámicos tienen mensajes porque todo sucede a través de una interfaz dual en lugar de saltos directos y compensados ​​en saltos vtable)?
Dmitry
3

Desde un punto de vista puramente teórico, no hay ninguna diferencia entre los dos: ha habido una serie de pruebas formales que muestran que los dos son completamente equivalentes, y que ambos pueden implementarse completamente en términos del otro.

Desde un punto de vista un poco menos teórico, hay una posible diferencia: en una implementación típica, la tabla de funciones virtuales está asignada estáticamente y el contenido de cada tabla se fija en tiempo de compilación. La búsqueda de mensajes, por el contrario, generalmente se realiza con algún tipo de objeto similar a un mapa, que suele ser dinámico, lo que significa que puede modificarlo en tiempo de ejecución. Esto hace que sea relativamente fácil agregar una nueva respuesta a un mensaje en una clase existente. Desafortunadamente, en la mayoría de los casos esto sigue siendo principalmente teórico. Primero, básicamente se trata de código auto modificable, que la mayoría de la gente decidió que fue una muy mala idea durante mucho tiempohace tiempo. En segundo lugar, para que sea muy significativo, necesita poder compilar un nuevo código en la clase existente para responder al nuevo mensaje que admite. Sin eso, todo lo que gana es la capacidad de agregar dinámicamente un nuevo nombre para un método existente.

Como implica el final del párrafo anterior, desde un punto de vista verdaderamente práctico, hay muy poca diferencia entre los dos. Son simplemente dos (muy ligeramente) diferentes formas de soportar la unión tardía. Aunque la búsqueda basada en mensajes generalmente es un poco más lenta, sería bastante inusual que la diferencia sea realmente significativa. Para la mayoría de los propósitos prácticos, son solo dos formas diferentes de lograr lo mismo.

Jerry Coffin
fuente
2
¿Tiene referencias que muestran las pruebas? Me gustaría echar un vistazo. Hay una gran diferencia entre la invocación del método de Java y el envío de mensajes de Smalltalk, no solo por el enlace tardío, sino también por el desacoplamiento del remitente y el receptor: no se puede saber si el receptor de un mensaje lo procesa o reenvía el mensaje en, por ejemplo.
Frank Shearar
1

En Objective-C, los mensajes están enlazados tarde. Es decir, se resuelven en tiempo de ejecución. C # admite una construcción similar a través de la palabra clave dinámica que declara que un objeto también está vinculado tarde.

Michael Brown
fuente
0

Por lo general, las llamadas a métodos se resuelven en tiempo de compilación (a menos que use la reflexión en Java), mientras que los mensajes en el Objetivo C se envían en tiempo de ejecución.

Heiko Rupp
fuente
2
Si las llamadas a métodos se resuelven en tiempo de compilación, no está utilizando OOP, está utilizando azúcar sintáctico para funciones sobrecargadas que toman structcomo primer parámetro. La unión tardía es una parte esencial del polimorfismo y, por lo tanto, de la POO.
2
Si. Pero aún así solo puede codificar una llamada de método contra algo (en Java) que es bien conocido en tiempo de compilación. Llamar a MyObject.foo () dará un error si MyObject o MyInterface no tienen definido el método foo (). ObjC permitirá enviarle un mensaje 'foo' para objetar MyObject, y si MyObject no tiene 'foo', esto bombardeará en tiempo de ejecución.
Heiko Rupp
¿Pensé que el objetivo C era un lenguaje compilado?
Vidar
1
Eso no está relacionado con el enlace temprano / tardío (tipeo dinámico versus tipig estructural; en su ejemplo, las llamadas al método se verifican en tiempo de compilación pero no necesariamente se envían ). @Vidar: lo es, pero agrega magia para las características dinámicas. También puedes compilar Python.
@Vidar: No es un problema de compilado versus interpretado, sino más bien estático vs. dinámico. En lenguajes OOP estáticos como Java, el compilador verifica para asegurarse de que una clase defina un método durante la fase de compilación. En un lenguaje de tipo dinámico como Objective-C, los mensajes se pasan en tiempo de ejecución.
mipadi
-1

Los mensajes son manejados por el núcleo o por el propio lenguaje (para ObjC, por ejemplo, hay un código de ensamblaje muy pequeño que lo hace).

En el kernel de Linux, por ejemplo, los mensajes se realizan con llamadas / funciones del sistema: puede encontrarlos si busca la programación del sistema Unix.

La diferencia principal entre una llamada al método y un mensaje es esta:

  • una llamada al método solo ocurre en su código: en ASM se traduce mediante un PUSH de los argumentos pasados.

  • un mensaje de kernel es principalmente algo enviado al kernel que se rastrea y devuelve a ciertos procesos. Puedo confundirlos con tuberías, pero lo que sea: sepa que ya existe un mecanismo que le permite ejecutar varios programas al mismo tiempo y dejar que se comuniquen al mismo tiempo. Por supuesto, no espere que esto funcione de la misma manera en Windows u otro sistema operativo.

jokoon
fuente
Esto no es "pasar mensajes", ya que se aplica a los lenguajes de programación.
mipadi