Sé Java y ahora estoy aprendiendo Objective-C. ¿Cuáles son exactamente las diferencias entre las interfaces Java y los protocolos Objective-C?
Sé Java y ahora estoy aprendiendo Objective-C. ¿Cuáles son exactamente las diferencias entre las interfaces Java y los protocolos Objective-C?
Respuestas:
Primero, una pequeña perspectiva histórica sobre el tema , de uno de los creadores de Java. A continuación, Wikipedia tiene una sección moderadamente útil sobre los protocolos Objective-C . En particular, comprenda que Objective-C admite tanto protocolos formales (que se declaran explícitamente con la @protocol
palabra clave, el equivalente de una interfaz Java) como protocolos informales (solo uno o más métodos implementados por una clase, que se pueden descubrir mediante 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 es de esperar en Java. A diferencia de Java (como mencionó skaffman ), 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 (usando -conformsToProtocol :) así:
if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
...
}
NOTA: la documentación de Apple dice:
"Este método determina la conformidad únicamente sobre la base de las declaraciones formales en los archivos de encabezado, como se ilustra arriba. No verifica si los métodos declarados en el protocolo están realmente implementados; eso es responsabilidad del programador".
A partir de Objective-C 2.0 (en OS X 10.5 "Leopard" e iOS), los protocolos formales ahora pueden definir métodos opcionales y una clase se ajusta a un protocolo siempre que implemente todos los métodos requeridos. Puede usar las palabras clave @required
(predeterminadas) y @optional
para alternar si las declaraciones de método que siguen deben o pueden implementarse para ajustarse al protocolo. (Consulte la sección de la guía del lenguaje de programación Objective-C 2.0 de Apple que analiza los métodos de protocolo opcionales ).
Los métodos de protocolo opcionales brindan mucha flexibilidad a los desarrolladores, particularmente para implementar delegados y oyentes . En lugar de extender algo como MouseInputAdapter (que puede ser molesto, ya que Java también es de herencia única) o implementar muchos métodos vacíos e inútiles, puede adoptar un protocolo e implementar solo los métodos opcionales que le interesan. Con este patrón, la persona que llama verifica si el método está implementado antes de invocarlo (usando -respondsToSelector ) así:
if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) {
[myObject fillArray:anArray withObject:foo];
...
}
Si la sobrecarga de reflexión se convierte en un problema, siempre puede almacenar en caché el resultado booleano para su reutilización , pero resista la tentación de optimizar prematuramente. :-)
-conformsToProtocol:
solo devolverá YES si la clase adopta explícitamente el protocolo. ¿Lo has probado siquiera?
-conformsToProtocol:
hecho requiere que la clase (o un antepasado) declare formalmente que adopta el protocolo. No estoy seguro de cómo me equivoqué, ¡gracias por la corrección!
Son casi idénticos. Sin embargo, lo único que me ha sorprendido es que, a menos que declare explícitamente que un protocolo C objetivo también implementa NSObject, las referencias a ese protocolo no tienen acceso a los métodos que declara NSObject (sin una advertencia del compilador de todos modos). Con java puede tener una referencia a una interfaz y aún llamar a toString (), etc. en ella.
p.ej
C objetivo:
@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