Diferenças entre interfaces Java e protocolos Objective-C?

93

Eu conheço Java e agora estou aprendendo Objective-C. Quais são exatamente as diferenças entre as interfaces Java e os protocolos Objective-C?

Arne Evertsson
fonte

Respostas:

82

Em primeiro lugar, uma pequena perspectiva histórica sobre o tema , de um dos criadores do Java. A seguir, a Wikipedia tem uma seção moderadamente útil sobre os protocolos Objective-C . Em particular, entenda que Objective-C suporta tanto protocolos formais (que são declarados explicitamente com a @protocolpalavra - chave, o equivalente a uma interface Java) e protocolos informais (apenas um ou mais métodos implementados por uma classe, que podem ser descobertos por reflexão).

Se você adotar um protocolo formal (terminologia Objective-C para "implementar uma interface"), o compilador emitirá avisos para métodos não implementados, assim como você esperaria em Java. Ao contrário do Java (como skaffman mencionou), se uma classe Objective-C implementa os métodos contidos em um protocolo formal, ela está "em conformidade" com esse protocolo, mesmo que sua interface não o adote explicitamente.Você pode testar a conformidade do protocolo no código (usando -conformsToProtocol :) como este:

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

NOTA: A documentação da Apple afirma:

"Este método determina a conformidade somente com base nas declarações formais em arquivos de cabeçalho, conforme ilustrado acima. Ele não verifica se os métodos declarados no protocolo estão realmente implementados - isso é responsabilidade do programador."

A partir do Objective-C 2.0 (no OS X 10.5 "Leopard" e iOS), os protocolos formais agora podem definir métodos opcionais e uma classe está em conformidade com um protocolo, desde que implemente todos os métodos necessários. Você pode usar as palavras-chave @required(padrão) e @optionalpara alternar se as declarações de método a seguir devem ou podem ser implementadas para estar em conformidade com o protocolo. (Consulte a seção do guia de linguagem de programação Objective-C 2.0 da Apple que discute métodos opcionais de protocolo .)

Os métodos de protocolo opcionais oferecem muita flexibilidade para os desenvolvedores, especialmente para implementar delegados e ouvintes . Em vez de estender algo como MouseInputAdapter (o que pode ser irritante, já que Java também é de herança única) ou implementar muitos métodos vazios e inúteis, você pode adotar um protocolo e implementar apenas os métodos opcionais de seu interesse. Com esse padrão, o chamador verifica se o método está implementado antes de invocá-lo (usando -respondsToSelector ) da seguinte maneira:

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

Se a sobrecarga de reflexão se tornar um problema, você sempre pode armazenar em cache o resultado booleano para reutilização , mas resista ao impulso de otimizar prematuramente. :-)

Quinn Taylor
fonte
4
"Se você adotar um protocolo formal (terminologia Objective-C para" implementar uma interface "), o compilador emitirá avisos para métodos não implementados, exatamente como você esperaria em Java." Java emitiria um erro neste caso, não um aviso.
Raffi Khatchadourian
3
"se uma classe Objective-C implementa os métodos contidos em um protocolo formal, ela está" em conformidade "com esse protocolo, mesmo que sua interface não o adote explicitamente. Você pode testar a conformidade do protocolo no código (usando -conformsToProtocol: ) como este "Isso é FALSO. -conformsToProtocol:só retornará SIM se a classe adotar explicitamente o protocolo. Você já experimentou?
user102008
2
Você está correto, -conformsToProtocol:realmente exige que a classe (ou um ancestral) declare formalmente que adota o protocolo. Não tenho certeza de como entendi errado, obrigado pela correção!
Quinn Taylor
18

Eles são quase idênticos. No entanto, a única coisa que me surpreendeu é que, a menos que você declare explicitamente que um protocolo C objetivo também implementa NSObject, as referências a esse protocolo não obtêm acesso aos métodos que NSObject declara (sem um aviso do compilador de qualquer maneira). Com o java, você pode ter uma referência a uma interface e ainda chamar toString () etc. nela.

por exemplo

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 (fixo):

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

id <MyProtocol> myProtocol;

[myProtocol retain] // No Warning
Tom Jefferys
fonte
25
Isso ocorre porque id e NSObject não são iguais . Em Java, o objeto raiz é Object. Em Objective-C, NSObject é um objeto raiz, mas não o objeto raiz. Se você deseja acessar todos os métodos NSObject (métodos de classe e também protocolos), indique explicitamente: NSObject <MyProtocol> myProtocol; ao invés de: id <MyProtocol> ... Quando você usa id você está dizendo: Eu não me importo com o objeto, só com o protocolo, que no seu caso não é verdade.
Jason Coco