Il trasferimento dei messaggi è un modo diverso di gestire il bisogno nel codice OO di un oggetto per ottenere un altro oggetto (o potenzialmente se stesso) per fare qualcosa.
Nella maggior parte dei linguaggi moderni che discendono dall'approccio C ++ lo facciamo con le chiamate ai metodi. In questo caso l'oggetto chiamato (tramite la sua definizione di classe) mette una grande lista di ciò che il metodo chiama accetta e quindi il codificatore dell'oggetto chiamante semplicemente scrive la chiamata:
public void doSomething ( String input )
...
other_object.dosomething ( local )
Per linguaggi tipizzati staticamente, il compilatore può quindi controllare il tipo di cosa chiamata e confermare che il metodo è stato dichiarato. Per le lingue digitate dinamicamente, viene eseguita in fase di runtime.
In pratica, tuttavia, ciò che accade è che un fascio di variabili viene inviato a uno specifico blocco di codice.
Passaggio del messaggio
Nei linguaggi di passaggio dei messaggi (come l'Objective C) invece dei metodi ci sono i ricevitori, ma in generale l'approccio di definirli e chiamarli è praticamente lo stesso - la differenza è il modo in cui è gestita.
In un messaggio passato alla lingua il compilatore può controllare che il ricevitore che hai chiamato esista, ma nel peggiore dei casi verrà visualizzato un avviso per dire che non è sicuro che sia lì. Questo perché in fase di esecuzione ciò che accadrà è che un blocco di codice sull'oggetto ricevente verrà chiamato passando sia il fascio di variabili che la firma del destinatario che si desidera chiamare. Quel blocco di codice cerca quindi il ricevitore e lo chiama. Tuttavia, se il ricevitore non esiste, il codice restituirà semplicemente un valore predefinito.
Di conseguenza, una delle stranezze riscontrate durante lo spostamento da C ++ / Java - > L'obiettivo C sta nel comprendere che è possibile "chiamare un metodo" su un oggetto che non è stato dichiarato sul tipo in fase di compilazione e che non esisteva nemmeno sul tipo di runtime ... e che la chiamata non avrebbe comportato un'eccezione viene lanciata ma in realtà un risultato viene passato indietro.
I vantaggi di questo approccio sono che appiattisce la gerarchia delle sottoclassi ed evita la maggior parte delle esigenze di interfacce / tipi di ereditarietà / anatra multipli. Permette anche agli oggetti di definire il comportamento predefinito quando viene richiesto di fare qualcosa per il quale non hanno un ricevitore (comunemente "se non lo faccio, inoltra la richiesta a questo altro oggetto"). Può anche semplificare il collegamento ai callback (ad esempio per gli elementi dell'interfaccia utente e gli eventi programmati) in particolare su linguaggi tipizzati staticamente come Java (in modo che il pulsante possa chiamare il ricevitore "runTest" piuttosto che chiamare il metodo "actionPerformed" sulla classe interna "RunTestButtonListener" che ti chiama).
Tuttavia, sembrerebbe essere a costo della necessità di ulteriori verifiche da parte dello sviluppatore che la chiamata che pensano di fare sia sull'oggetto giusto con il tipo giusto e che passi i parametri giusti nell'ordine giusto, perché il il compilatore potrebbe non avvisarti e funzionerà perfettamente in fase di esecuzione (solo restituendo una risposta predefinita). C'è anche un colpo di prestazioni dalla ricerca extra e dal passaggio dei parametri.
In questi giorni, le lingue digitate dinamicamente possono offrire molti vantaggi del messaggio inviato OO con meno problemi.