objective-c中的首选是什么:id或显式类型?

时间:2011-01-16 00:02:36

标签: objective-c

什么更好,为什么?

在类init方法和代码中的常用变量等情况下,哪种情况更好?

5 个答案:

答案 0 :(得分:11)

  

什么更好,为什么?

明确的输入信息总是更好,除非你因某些原因无法使用它(见下文)。

它允许编译器更严格地验证代码,并在编译时捕获许多错误,否则会导致应用程序在运行时崩溃。

很久很久以前,API中的所有内容都使用id。事实证明这是一个完全痛苦的对接;脆弱,并导致许多崩溃,这些崩溃本来会被特定类型捕获。

所以,它改变了。 (这是〜1994年)。

  

在这种情况下有什么好处   类init方法和通常的   代码中的变量?

对于init,您别无选择,只能使用通用(id)返回类型。 Objective-C不支持共变量或反变量声明,也没有一种机制来推广init的声明,同时还提供对特定类型检查的支持。

同样适用于retainobjectAtIndex:addObject:以及许多其他方法,这些方法接受或返回多种对象中的一种(或将其作为参数)。

而且,不,idNSView*之间绝对没有任何性能差异。

  

你可以在明确时给出一个例子   打字会引起问题吗?

如果你写了:

- (MyClass *) init;

在子类中:

- (MySubclass *) init;

你最有可能得到编译器警告,或者你必须对wazoo进行类推。

答案 1 :(得分:5)

在clang的最新版本(在Lion中),您实际上不应该返回id,而是返回instancetype。这是一个在返回类型中使用的关键字,用于指定它返回的类型是接收消息的类的实例。它现在是OS X Lion上init方法的首选返回类型。

答案 2 :(得分:4)

显式输入提供构建时保护,如果您对可能无法正常工作的内容进行转换或执行操作等操作,则会通知您可能出现的问题。

显式打字还有助于防止输入错误的对象的非明显转移,这是通过您未考虑的代码中的路径传播的结果。在程序经过大量测试之后,这种错误通常不会变得清晰,更常见的是在发布之后。

对于未来的程序员(包括你未来的自己)也很有帮助,试图使用你的代码,使他们更有可能一眼就知道一个对象应该是什么。因此,它使代码更加“自我记录”。

有些东西不能有意义的类型,因为实际上没有类型适用。其他时候您需要使用id因为您需要能够接受任何类型的对象。例如,Cocoa Touch在引用消息的sender时会使用它,因为任何东西都可以发送它;指定显式类型根本不起作用。

绝大多数时候,显性类型对您有利。

答案 3 :(得分:2)

尽可能使用特定类型,但不是更多。考虑如何使用任何特定的变量,参数或返回类型并适当地设置其类型。

例如,UITableView的dataSource属性声明为id<UITableViewDataSource>,因为表视图只关心其数据源是符合UITableViewDataSource协议的对象。这允许数据源足够灵活,可以与任何实现协议的特定类一起使用,但如果您尝试将未实现该协议的对象分配为数据源,则仍允许编译器发出警告。

如果你太具体了,那么你的代码变得不灵活,只接受非必要的特定实现(即当你可以真正使用任何NSString时要求NSMutableString)。

如果你太模糊(例如,输入id所有内容),那么你就无法识别何时将未识别的选择器发送到特定实例,并且编译器无法识别任何数量的无效语句。

对于init方法,请遵循The Objective-C Programming Language

中的建议
  

初始化方法的返回类型应为id。

     

这样做的原因是id表示该类是故意不被考虑的 - 该类是未指定的并且可能会发生变化,具体取决于调用的上下文。例如,NSString提供了一个方法initWithFormat:。但是,当发送到NSMutableString(NSString的子类)的实例时,该消息返回NSMutableString的实例,而不是NSString。 (另请参阅“组合分配和初始化”中给出的单例示例。)

答案 4 :(得分:0)

我认为两者之间没有性能差异。 您可以让id返回init类型,因为您可以转换init的结果。

例如:

Toto *foo = [[Toto alloc] init];
id foo2 = [[Toto alloc] init]; 

两者都有效,但您必须像foo2一样强制转换(Toto *)foo变量,以便在不创建编译器警告的情况下访问实例的属性或方法。即使它工作正常......

我认为一些开发人员会使用id,因为他们只是通过变量槽实例传递而不使用它。这种使用允许不导入.h

的问候,
KL94