Diferenças entre mensagens e métodos?

13

No Objetivo C, você tem o conceito de enviar mensagens para outros objetos e, bem, isso é muito semelhante à chamada de método em linguagens como C # e Java.

Mas quais são exatamente as diferenças sutis? Como devo pensar em mensagens ao pensar no meu código?

Nota: Apenas um pouco de experiência aqui, sou um desenvolvedor de C # / Java tentando entender alguns conceitos sobre o Objetivo C.

Vidar
fonte
2
Como todos são idiomas diferentes, as diferenças não são sutis. Eles são idiomas diferentes. "ao pensar no meu código"? Qual código? Ao pensar em Java ou C #, você não pensa em mensagens. Você pensa em métodos. Você pode esclarecer como linguagens não relacionadas com conceitos não relacionados podem ter diferenças "sutis"?
S.Lott 11/11
1
Por favor, faça sua pergunta no stackoverflow.com
Amir Rezaei
1
Esta pergunta deve realmente estar no StackOverflow? É uma pergunta sobre conceitos de programação, não um problema sobre algum código que tenho. Talvez eu esteja errado, eu não sei - as fronteiras estão a esbater ...
Vidar
1
@Vidar, a questão não é subjetiva. Você está procurando uma definição de livro didático. Programadores é mais para opiniões, experiência e perguntas subjetivas.
Stephen Furlani
1
OK - existe uma maneira de fazer com que o moderador mova essa pergunta para o StackOverflow?
Vidar

Respostas:

10

Uma mensagem é o nome de um seletor e os parâmetros para esse seletor.

Um seletor é um símbolo.

Um método é um pedaço de código em uma classe identificada por um seletor.

Em outras palavras, [foo bar: baz]diz "envie a mensagem chamada @selector(bar:)com parâmetro bazpara objeto foo. Você pode enviar essa mensagem para muitos objetos diferentes.

Por outro lado, o método bar: para um Foopode parecer

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

mas por um FooTwopode parecer

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

(Espero ter a sintaxe correta; já faz um tempo desde que toquei o Objective-C pela última vez.)

Quando você envia a mensagem, o kernel Objective-C despacha a mensagem para a fooqual decide se entende a mensagem. Ele decide isso com base em se pode encontrar um método identificado por esse seletor.

Dois métodos com o mesmo nome e uma mensagem.

Também é possível que um objeto simplesmente encaminhe uma mensagem específica (ou conjunto de mensagens) para outro objeto para processamento. Nesse caso, você envia uma mensagem para esse objeto proxy, que não possui métodos para corresponder a essa mensagem , e o proxy encaminha a mensagem para seu objeto agrupado.

Frank Shearar
fonte
então ... uma mensagem é quando você chama uma dispinterface (a.invoke selector, args) e um método é quando você chama uma interface (a.methodName)? Isso não tornaria java, JavaScript, todas as linguagens dinâmicas com mensagens, porque tudo acontece através da interface dupla, em vez de saltos diretos e deslocados para saltos de vtable)?
Dmitry
3

Do ponto de vista puramente teórico, não há nenhuma diferença entre os dois - houve várias provas formais mostrando que os dois são completamente equivalentes e que podem ser implementados inteiramente em termos do outro.

De um ponto de vista um pouco menos teórico, há uma diferença possível: em uma implementação típica, a tabela de funções virtuais é alocada estaticamente e o conteúdo de cada vtable é fixado em tempo de compilação. A pesquisa de mensagens, por outro lado, geralmente é feita com algum tipo de objeto parecido com um mapa, que é tipicamente dinâmico, o que significa que você pode modificá-lo em tempo de execução. Isso torna relativamente fácil adicionar uma nova resposta a uma mensagem em uma classe existente. Infelizmente, na maioria dos casos, isso permanece principalmente teórico. Primeiro, você está basicamente lidando com código auto-modificável, que a maioria das pessoas decidiu que era uma péssima ideia por muito tempotempo atrás. Segundo, para torná-lo muito significativo, é necessário que você consiga compilar o novo código na classe existente para responder à nova mensagem que você suporta. Sem isso, tudo o que você ganha é a capacidade de adicionar dinamicamente um novo nome para um método existente.

Como está implícito no final do parágrafo anterior, de um ponto de vista verdadeiramente prático, há muito pouca diferença entre os dois. Eles são simplesmente duas maneiras (muito pouco) diferentes de apoiar a ligação tardia. Embora a pesquisa baseada em mensagens seja geralmente um pouco mais lenta, seria bastante incomum que a diferença fosse realmente significativa. Para fins mais práticos, são apenas duas maneiras diferentes de realizar a mesma coisa.

Jerry Coffin
fonte
2
Você tem referências mostrando as provas? Eu gostaria de dar uma olhada. Há uma grande diferença entre a invocação do método Java e o envio de mensagens do Smalltalk, não apenas por causa da ligação tardia, mas também por causa da dissociação do remetente e do destinatário: você não pode dizer se o destinatário de uma mensagem a processa ou a encaminha. por exemplo.
Frank Shearar
1

No Objective-C, as mensagens são atrasadas. Ou seja, eles são resolvidos em tempo de execução. O C # suporta uma construção semelhante por meio da palavra-chave Dynamic, que também declara um objeto como atrasado.

Michael Brown
fonte
0

Normalmente, as chamadas de método são resolvidas no tempo de compilação (a menos que você use reflexão em Java), enquanto as mensagens no Objetivo C são despachadas no tempo de execução.

Heiko Rupp
fonte
2
Se as chamadas de método são resolvidas no tempo de compilação, você não está usando OOP, você está usando açúcar sintático para funções sobrecarregadas usando o structprimeiro parâmetro. O bindung tardio é uma parte essencial do polimorfismo e, portanto, da POO.
2
Sim. Mas você ainda pode codificar apenas uma chamada de método em algo (em Java) que é bem conhecido em tempo de compilação. Chamar MyObject.foo () causará um erro se MyObject ou MyInterface não tiver um método foo () definido. O ObjC permitirá enviar uma mensagem 'foo' para objetar o MyObject - e se o MyObject não tiver 'foo', isso ocorrerá em tempo de execução.
Heiko Rupp
Eu pensei que o Objetivo C fosse uma linguagem compilada?
Vidar
1
Isso é inalterado na ligação antecipada / tardia (tipagem dinâmica versus tipologia estrutural - no seu exemplo, as chamadas de método são verificadas no tempo de compilação, mas não são necessariamente despachadas ). @ Vidar: É, mas adiciona mágica para recursos dinâmicos. Você também pode compilar Python.
@ Vidar: Não é uma questão de compilado vs. interpretado, mas sim estático vs. dinâmico. Em linguagens OOP estáticas como Java, o compilador verifica se uma classe define um método durante a fase de compilação. Em uma linguagem de tipo dinâmico como Objective-C, as mensagens são passadas em tempo de execução.
Mipadi
-1

As mensagens são tratadas pelo kernel ou pelo próprio idioma (para o ObjC, por exemplo, existe um código de assembly muito pequeno).

No kernel do linux, por exemplo, as mensagens são feitas com chamadas / funções do sistema: você pode encontrá-las se pesquisar sobre a programação do sistema unix.

A principal diferença entre uma chamada de método e uma mensagem é esta:

  • uma chamada de método acontece apenas no seu código: no ASM, ela é traduzida por um push dos argumentos passados.

  • uma mensagem do kernel é principalmente algo enviado ao kernel que é rastreado e enviado de volta a certos processos. Posso confundi-los com pipes, mas seja o que for: saiba que já existem mecanismos que permitem executar vários programas ao mesmo tempo e permitir a comunicação ao mesmo tempo. Obviamente, não espere que isso funcione da mesma maneira no Windows ou em outro sistema operacional.

jokoon
fonte
Isso não é "passagem de mensagem", pois se aplica a linguagens de programação.
Mipadi