Eu estudei programação OO, principalmente em C ++, C # e Java. Eu pensei que tinha uma boa noção sobre isso com meu entendimento de encapsulamento, herança e polimorfismo (além de ler muitas perguntas neste site).
Uma coisa que parece surgir aqui e ali é o conceito de "passagem de mensagem". Aparentemente, isso é algo que não é usado durante a programação OO nas principais linguagens de hoje, mas é suportado pelo Smalltalk.
Minhas perguntas são:
- O que é a passagem de mensagens? (Alguém pode dar um exemplo prático?)
- Existe algum suporte para essa "mensagem que passa" em C ++, C # ou Java?
java
c#
c++
object-oriented
Tom
fonte
fonte
Respostas:
A passagem de mensagens significa simplesmente que (em um nível muito abstrato) o mecanismo fundamental da execução do programa são objetos enviando mensagens uns aos outros. O ponto importante é que o nome e a estrutura dessas mensagens não são necessariamente fixados previamente no código-fonte e podem ser informações adicionais. Esta é uma parte importante do que Alan Kay originalmente imaginou como "programação orientada a objetos".
Esses idiomas implementam uma versão limitada da mensagem passando por chamadas de método. Limitado porque o conjunto de mensagens que podem ser enviadas é limitado aos métodos declarados em uma classe. A vantagem dessa abordagem é que ela pode ser implementada com muita eficiência e permite uma análise estática de código muito detalhada (o que resulta em todos os tipos de benefícios úteis, como a conclusão de código).
Por outro lado, as linguagens que implementam a passagem de mensagens "real" geralmente também possuem definições de método, como uma maneira conveniente de implementar manipuladores de mensagens, mas permitem que as classes implementem manipuladores de mensagens mais flexíveis que permitem ao objeto receber "chamadas de método" com nomes arbitrários (não corrigidos em tempo de compilação).
Um exemplo no Groovy que demonstra o poder desse conceito:
irá produzir este XML:
Note-se que
records
,car
,country
erecord
são sintaticamente chamadas de método, mas não existem métodos de que o nome definido noMarkupBuilder
. Em vez disso, ele possui um manipulador de mensagens catchall que aceita todas as mensagens e interpreta os nomes das mensagens como o nome de um elemento XML, os parâmetros como atributos e os fechamentos como elementos filhos.fonte
sendMessage(property_name, Array of arguments)
egetMessage(property_name, Array of arguments)
estática?A passagem de mensagens é uma maneira diferente de lidar com a necessidade no código OO de um objeto fazer com que outro objeto (ou potencialmente ele mesmo) faça alguma coisa.
Na maioria das linguagens modernas que descendem da abordagem C ++, fazemos isso com chamadas de método. Nesse caso, o objeto chamado (por meio de sua definição de classe) coloca uma grande lista do método que ele aceita e, em seguida, o codificador do objeto que chama chama simplesmente a chamada:
Para linguagens de tipo estaticamente, o compilador pode verificar o tipo de coisa que está sendo chamada e confirmar que o método foi declarado. Para idiomas digitados dinamicamente, isso é realizado em tempo de execução.
Mas, em essência, o que acontece é que um pacote de variáveis é enviado para um bloco de código específico.
Passagem de mensagem
Em linguagens de transmissão de mensagens (como o Objetivo C), em vez de métodos, existem receptores, mas, de maneira geral, a abordagem para defini-los e chamá-los é praticamente a mesma - a diferença é a maneira como são manipulados.
Em uma linguagem transmitida por mensagem, o compilador pode verificar se o destinatário que você chamou existe, mas, na pior das hipóteses, ele exibirá um aviso para dizer que não tem certeza de que está lá. Isso ocorre porque, em tempo de execução, o que acontecerá é que um bloco de código no objeto receptor será chamado passando o pacote de variáveis e a assinatura do destinatário que você deseja chamar. Esse bloco de código procura o receptor e o chama. No entanto, se o receptor não existir, o código simplesmente retornará um valor padrão.
Como resultado, uma das esquisitices encontradas ao passar de C ++ / Java -> Objetivo C é entender que você pode "chamar um método" em um objeto que não foi declarado no tipo de tempo de compilação e nem sequer existia em o tipo de tempo de execução ... e que a chamada não resultaria em uma exceção, mas na verdade um resultado seria devolvido.
As vantagens dessa abordagem são que elas nivelam a hierarquia da subclasse e evitam a maioria das necessidades de interfaces / herança múltipla / tipos de patos. Ele também permite que os objetos definam o comportamento padrão quando solicitados a fazer algo para o qual eles não têm um receptor (normalmente "se eu não fizer isso, encaminhe a solicitação para esse outro objeto"). Ele também pode simplificar a vinculação a retornos de chamada (por exemplo, para elementos da interface do usuário e eventos programados), especialmente em linguagens de tipo estatístico, como Java (para que o botão chame o receptor de "runTest" em vez de chamar o método "actionPerformed" na classe interna "RunTestButtonListener", que faz a chamada para você).
No entanto, parece que está à custa da necessidade de verificação adicional pelo desenvolvedor de que a chamada que eles pensam estar fazendo está no objeto certo com o tipo certo e passando os parâmetros certos na ordem certa, porque o compilador pode não avisá-lo e ele funcionará perfeitamente bem em tempo de execução (retornando apenas uma resposta padrão). Também há, sem dúvida, um impacto no desempenho com a pesquisa extra e a passagem de parâmetros.
Atualmente, os idiomas digitados dinamicamente podem oferecer muitos benefícios da mensagem passada OO com menos problemas.
fonte
As arquiteturas de transmissão de mensagens são simplesmente sistemas em que cada componente é independente dos outros, com um mecanismo comum para transmitir dados entre eles. Você pode considerar as chamadas de método como uma forma de passagem de mensagens, mas não é prático fazê-lo - isso confunde o problema. Isso ocorre porque se você tem uma classe com métodos bem definidos e algum código que chama esses métodos, a coisa toda deve ser compilada, acoplando o código e o objeto. você pode ver como está próximo (quando uma mensagem está sendo passada e o compilador está aplicando a correção, mas perde grande parte da flexibilidade de um sistema dissociado).
As arquiteturas de transmissão de mensagens geralmente permitem que objetos sejam adicionados em tempo de execução e, mais frequentemente, permitem que as mensagens sejam redirecionadas para um ou mais objetos. Para que eu possa ter algum código que transmita uma mensagem 'dados x são atualizados' para todos os objetos que foram carregados no sistema, e cada um deles pode executar qualquer ação que desejar com essas informações.
Um exemplo estranho é a web. HTTP é um sistema de transmissão de mensagens - você passa um verbo de comando e um 'pacote de dados' para um processo do servidor. (por exemplo, GET http: \ myserver \ url) Nem o seu navegador nem o servidor da web se preocupam com os dados que você envia ou para onde os envia. O servidor o passará para o código que irá empacotar outro 'pacote' de dados e o enviará de volta para você. Nenhum componente deste sistema sabe algo sobre o trabalho dos outros ou o que eles fazem, apenas conhece o protocolo usado para a comunicação da mensagem.
fonte