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


Answers:


82

首先,从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];
    ...
}

如果反射的开销成为问题,则始终可以缓存布尔结果以供重用,但可以避免过早优化的冲动。:-)


4
“如果您采用正式协议(Objective-C术语表示“实现接口”),则编译器将针对未实现的方法发出警告,就像您在Java中所期望的那样。” 在这种情况下,Java会发出错误,而不是警告。
拉菲·哈查杜安

3
“如果Objective-C类实现了正式协议中包含的方法,那么即使它的接口未明确采用它,也可以说它“符合”该协议。您可以在代码中测试协议的一致性(使用-conformsToProtocol: ),例如“这是FALSE。-conformsToProtocol:如果该类明确采用了协议,则只会返回YES。你试过了吗?
user102008

2
您是正确的,-conformsToProtocol:确实确实要求该类(或祖先)正式声明它采用了该协议。不知道我怎么弄错了,感谢您的纠正!
奎因·泰勒

18

它们几乎是相同的。但是,让我着迷的一件事是,除非您明确声明目标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

25
这是因为id和NSObject 不相同。在Java中,根对象是Object。在Objective-C,NSObject的是根对象,但不是所述根对象。如果要访问所有NSObject方法(类方法以及协议),请明确声明:NSObject <MyProtocol> myProtocol; 代替:id <MyProtocol> ...当您使用id时,您的意思是:我不在乎对象,关心协议,在您的情况下是不正确的。
杰森·可可
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.