Java接口和Objective-C协议之间的区别?

Arn*_*son 92 java objective-c

我认识Java,现在我正在学习Objective-C.Java接口和Objective-C协议之间究竟有什么区别?

Qui*_*lor 81

首先,从Java的创建者之一开始,对该主题进行一些历史性的观察.接下来,Wikipedia 对Objective-C协议有一个中等帮助的部分.特别要理解的是,Objective-C支持正式协议(使用@protocol关键字显式声明,相当于Java接口)和非正式协议(只有一个或多个类可以通过反射发现的方法).

如果采用正式协议(Objective-C术语"实现接口"),编译器将为未实现的方法发出警告,就像您在Java中所期望的那样. 与Java(如skaffman所提到的)不同,如果Objective-C类实现正式协议中包含的方法,则称其"符合"该协议,即使其接口未明确采用它.您可以在代码中测试协议一致性(使用-conformsToProtocol :),如下所示:

if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

注意:Apple的文档说明:

"这种方法仅根据头文件中的正式声明来确定一致性,如上所示.它不会检查协议中声明的方法是否实际实现 - 这是程序员的责任."

从Objective-C 2.0开始(在OS X 10.5"Leopard"和iOS中),正式协议现在可以定义可选方法,并且只要它实现了所有必需的方法,类就符合协议.您可以使用@required(默认)和@optional关键字来切换后面的方法声明是否必须可以实现以符合协议.(请参阅Apple的Objective-C 2.0编程语言指南中讨论可选协议方法的部分.)

可选的协议方法为开发人员提供了很大的灵活性,特别是对于实现委托监听器.而不是扩展类似MouseInputAdapter(可能很烦人,因为Java也是单继承)或实现许多无意义的空方法,您可以采用协议并仅实现您关心的可选方法.使用此模式,调用者在调用之前检查方法是否已实现(使用-respondsToSelector),如下所示:

if ([myObject respondsToSelector:@selector(fillArray:withObject:)]) {
    [myObject fillArray:anArray withObject:foo];
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果反射的开销成为一个问题,你总是可以缓存布尔结果以便重用,但是要抵制过早优化的冲动.:-)

  • "如果您采用正式协议(Objective-C术语"实现接口"),编译器将为未实现的方法发出警告,就像您在Java中所期望的那样." 在这种情况下,Java会发出错误,而不是警告. (4认同)
  • "如果Objective-C类实现了正式协议中包含的方法,则称其"符合"该协议,即使其接口未明确采用它.您可以在代码中测试协议一致性(使用-conformsToProtocol: )像这样"这是假的.`-conformsToProtocol:`只有在类明确采用协议时才返回YES.你有没试过吗? (3认同)
  • 你是对的,`-conformsToProtocol:`确实要求类(或祖先)正式声明它采用协议.不知道我怎么弄错了,谢谢你的纠正! (2认同)

Tom*_*rys 18

它们几乎相同.然而,有一件事让我感到震惊的是,除非你明确声明一个客观的C协议也实现了NSObject,否则对该协议的引用无法访问NSObject声明的方法(无论如何都没有编译器警告).使用java,您可以引用一个接口,并仍然可以在其上调用toString()等.

例如

目标C:

@protocol MyProtocol
// Protocol definition
@end

id <MyProtocol> myProtocol;

 [myProtocol retain] // Compiler warning
Run Code Online (Sandbox Code Playgroud)

Java的:

public interface MyInterface {
// interface definition
}

MyInterface myInterface;

myInterface.toString();  // Works fine.
Run Code Online (Sandbox Code Playgroud)

目标C(固定):

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

id <MyProtocol> myProtocol;

[myProtocol retain] // No Warning
Run Code Online (Sandbox Code Playgroud)

  • 这是因为id和NSObject*不一样*.在Java中,根对象是Object.在Objective-C中,NSObject是一个根对象,但不是*根对象.如果要访问所有NSObject方法(类方法和协议),请明确说明:NSObject <MyProtocol> myProtocol; 而不是:id <MyProtocol> ...当你使用id时你会说:我不关心对象,*只关心*协议,在你的情况下不是真的. (25认同)