2009-06-13 12 views

risposta

80

Prima di tutto, un po 'di historical perspective on the topic, da uno dei creatori di Java. Successivamente, Wikipedia ha un utile moderato section on Objective-C protocols. In particolare, capire che Objective-C supporta entrambi i protocolli formali (che sono dichiarati esplicitamente con la parola chiave @protocol, l'equivalente di un'interfaccia Java) e protocolli informali (solo uno o più metodi implementati da una classe, che può essere scoperto tramite riflessione).

Se si adotta un protocollo formale (terminologia Objective-C per "implementare un'interfaccia") il compilatore emetterà avvisi per metodi non implementati, proprio come ci si aspetterebbe in Java. A differenza di Java (come skaffman menzionato), se una classe Objective-C implementa i metodi contenuti in un protocollo formale, si dice che "si conforma" a tale protocollo, anche se la sua interfaccia non la adotta esplicitamente. È possibile verificare la conformità del protocollo nel codice (utilizzando -conformsToProtocol:) come questo:

if ([myObject conformsToProtocol:@protocol(MyProtocol)]) { 
    ... 
} 

NOTA: Apple documentation stati:

"Questo metodo serve a determinare la conformità esclusivamente sulla base delle dichiarazioni formali nei file header , come illustrato sopra, non controlla se i metodi dichiarati nel protocollo sono effettivamente implementati, è responsabilità del programmatore. "

Come di Objective-C 2.0 (in OS X 10.5 "Leopard" e iOS), protocolli formali possono ora definire metodi opzionali, e una classe è conforme a un protocollo fintanto che implementa tutti i metodi necessari . È possibile utilizzare le parole chiave @required (predefinito) e @optional per alternare se le dichiarazioni di metodo successive a devono essere o possono essere implementate per conformarsi al protocollo. (Vedi la sezione della guida di Apple Objective-C 2.0 Programming Language che parla di optional protocol methods.)

metodi del protocollo opzionali aprono molta flessibilità agli sviluppatori, in particolare per l'attuazione delegati e ascoltatori. Invece di estendere qualcosa come un MouseInputAdapter (che può essere fastidioso, dal momento che Java è anche ad ereditarietà singola) o implementando molti metodi inutili e vuoti, puoi adottare un protocollo e implementare solo i metodi opzionali che ti interessano. Con questo modello, il chiamante controlla se il metodo è implementato prima di richiamare (usando -respondsToSelector) in questo modo:

if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) { 
    [myObject fillArray:anArray withObject:foo]; 
    ... 
} 

Se il sovraccarico di riflessione diventa un problema, si può sempre cache the boolean result for reuse, ma resistere alla tentazione di ottimizzare prematuramente . :-)

+4

"Se si adotta un protocollo formale (terminologia Objective-C per" implementare un'interfaccia ") il compilatore emetterà avvisi per metodi non implementati, proprio come ci si aspetterebbe da Java." Java emetterebbe un errore in questo caso, non un avvertimento. –

+3

"se una classe Objective-C implementa i metodi contenuti in un protocollo formale, si dice che" conformi "a tale protocollo, anche se la sua interfaccia non lo adotta esplicitamente.È possibile testare la conformità del protocollo nel codice (usando -conformsToProtocol :) come questo "Questo è FALSO. '-conformsToProtocol:' restituirà SÌ solo se la classe adotta esplicitamente il protocollo. L'hai mai provato? – user102008

+2

Hai ragione, '-conformsToProtocol:' richiede effettivamente che la classe (o un antenato) dichiari formalmente che adotta il protocollo. Non sono sicuro di come ho sbagliato, grazie per la correzione! –

18

Sono quasi identici. Tuttavia, l'unica cosa che mi ha catturato è che, a meno che non dichiari esplicitamente che un protocollo C oggettivo implementa anche NSObject, i riferimenti a tale protocollo non ottengono l'accesso ai metodi dichiarati da NSObject (senza comunque un avvertimento del compilatore). Con java puoi avere un riferimento a un'interfaccia, e comunque chiamare toString() ecc.

esempio

Objective C:

@protocol MyProtocol 
// Protocol definition 
@end 

id <MyProtocol> myProtocol; 

[myProtocol retain] // Compiler warning 

Java:

public interface MyInterface { 
// interface definition 
} 

MyInterface myInterface; 

myInterface.toString(); // Works fine. 

Objective C (fisso):

@protocol MyProtocol <NSObject> 
// Protocol definition 
@end 

id <MyProtocol> myProtocol; 

[myProtocol retain] // No Warning 
+25

Questo perché ID e NSObject * non sono gli stessi *. In Java, l'oggetto radice è Object. In Objective-C, NSObject è un oggetto radice, ma non * l'oggetto radice *. Se si desidera accedere a tutti i metodi NSObject (metodi di classe e protocolli), dichiararlo esplicitamente: NSObject myProtocol; invece di: id ... Quando usi id stai dicendo: non mi interessa l'oggetto, * solo * il protocollo, che nel tuo caso non è vero. –

+0

@JasonCoco cool: D – hqt