2009-06-13 9 views

Respuesta

80

En primer lugar, un pequeño historical perspective on the topic, de uno de los creadores de Java. A continuación, Wikipedia tiene un section on Objective-C protocols moderadamente útil. En particular, entienda que Objective-C admite protocolos formales (que se declaran explícitamente con la palabra clave @protocol, el equivalente de una interfaz Java) y protocolos informales (solo uno o más métodos implementados por una clase, que pueden ser descubierto a través de la reflexión).

Si adopta un protocolo formal (terminología de Objective-C para "implementar una interfaz") el compilador emitirá advertencias para los métodos no implementados, tal como se esperaría en Java. A diferencia de Java (como skaffman mencionado), si una clase Objective-C implementa los métodos contenidos en un protocolo formal, se dice que "se ajusta" a ese protocolo, incluso si su interfaz no lo adopta explícitamente. Para probar la conformidad de protocolo en el código (usando -conformsToProtocol:) así:

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

NOTA: documentation estados de Apple:

"Este método determina la conformidad únicamente sobre la base de las declaraciones formales en los archivos de cabecera , como se ilustra arriba, no comprueba si los métodos declarados en el protocolo se implementan realmente, esa es la responsabilidad del programador ".

Como de Objective-C 2.0 (en OS X 10.5 "Leopard" y el IOS), protocolos formales ahora pueden definir métodos opcionales, y una clase se ajusta a un protocolo tal de que implementa todos los métodos requeridos . Puede usar las palabras clave @required (predeterminado) y @optional para alternar si las declaraciones de método que siguen a deben o pueden implementarse para cumplir con el protocolo. (Consulte la sección de la guía Objective-C 2.0 Programming Language de Apple que trata sobre optional protocol methods.)

conocer los protocolos opcionales abren una gran flexibilidad a los desarrolladores, en particular para la implementación de delegados y oyentes. En lugar de extender algo como un MouseInputAdapter (que puede ser molesto, ya que Java también es de herencia única) o implementar muchos métodos inútiles y vacíos, puede adoptar un protocolo e implementar solo los métodos opcionales que le interesan. Con este patrón, la persona que llama comprueba si el método se lleva a cabo antes de invocar (usando -respondsToSelector) de esta manera:

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

Si la sobrecarga de reflexión se convierte en un problema, siempre se puede cache the boolean result for reuse, pero resista la tentación de optimizar prematuramente . :-)

+4

"Si adopta un protocolo formal (terminología de Objective-C para" implementar una interfaz ") el compilador emitirá advertencias para los métodos no implementados, tal como se esperaría en Java". Java emitiría un error en este caso, no una advertencia. –

+3

"si una clase Objective-C implementa los métodos contenidos en un protocolo formal, se dice que se" ajusta "a ese protocolo, incluso si su interfaz no lo adopta explícitamente. Puede probar la conformidad del protocolo en el código (utilizando -conformToProtocol :) como este "Esto es FALSO. '-conformsToProtocol:' solo devolverá SÍ si la clase adopta explícitamente el protocolo. ¿Lo has intentado? – user102008

+2

Tiene razón, '-conformsToProtocol:' de hecho requiere que la clase (o un ancestro) declare formalmente que adopta el protocolo. No estoy seguro de cómo me equivoqué, ¡gracias por la corrección! –

18

Son casi idénticos. Sin embargo, lo único que me ha sorprendido es que, a menos que declare explícitamente que un protocolo Object C también implementa NSObject, las referencias a ese protocolo no tienen acceso a los métodos que declara NSObject (sin una advertencia de compilador de todos modos). Con java puede tener una referencia a una interfaz, y todavía llamar a String(), etc. en él.

por ejemplo

Objetivo 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. 

Objetivo C (fijo):

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

id <MyProtocol> myProtocol; 

[myProtocol retain] // No Warning 
+25

Esto se debe a que id y NSObject * no son lo mismo *. En Java, el objeto raíz es Object. En Objective-C, NSObject es un objeto raíz, pero no * el * objeto raíz. Si desea acceder a todos los métodos de NSObject (métodos de clase y protocolos), explíquelo explícitamente: NSObject myProtocol; en lugar de: id ... Cuando usa id, está diciendo: no me importa el objeto, * solo * el protocolo, que en su caso no es cierto. –

+0

@JasonCoco cool: D – hqt

Cuestiones relacionadas