我知道Java,现在正在学习Objective-C。Java接口和Objective-C协议之间到底有什么区别?
我知道Java,现在正在学习Objective-C。Java接口和Objective-C协议之间到底有什么区别?
Answers:
首先,从Java的一位创建者那里对该主题进行了一些历史性的展望。接下来,维基百科在Objective-C协议中提供了适度有用的部分。特别要了解,Objective-C支持正式协议(使用@protocol关键字明确声明,相当于Java接口)和非正式协议(仅一个或多个由类实现的方法,可以通过反射来发现)。
如果您采用正式协议(“实现接口”的Objective-C术语),则编译器将针对未实现的方法发出警告,就像您在Java中所期望的那样。 与Java(如skaffman所提到的)不同,如果Objective-C类实现形式化协议中包含的方法,则即使它的接口未明确采用它,也可以说它“符合”该协议。您可以在代码中测试协议一致性(使用-conformsToProtocol:),如下所示:
if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
...
}
注意: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];
...
}
如果反射的开销成为问题,则始终可以缓存布尔结果以供重用,但可以避免过早优化的冲动。:-)
-conformsToProtocol:如果该类明确采用了协议,则只会返回YES。你试过了吗?
-conformsToProtocol:确实确实要求该类(或祖先)正式声明它采用了该协议。不知道我怎么弄错了,感谢您的纠正!
它们几乎是相同的。但是,让我着迷的一件事是,除非您明确声明目标C协议也实现了NSObject,否则对该协议的引用将无法访问NSObject声明的方法(无论如何都不会出现编译器警告)。使用java,您可以引用一个接口,并仍然在其上调用toString()等。
例如
目标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.
目标C(固定):
@protocol MyProtocol <NSObject>
// Protocol definition
@end
id <MyProtocol> myProtocol;
[myProtocol retain] // No Warning