在objective-c中,哪一种更可取:id还是显式类型?

在objective-c中,哪一种更可取:id还是显式类型?,objective-c,Objective C,什么更好?为什么 在类init方法和代码中的常用变量等情况下,有什么更好的方法?显式键入提供了构建时保护,当您对可能不起作用的内容执行强制转换或执行操作时,会通知您可能出现的问题 显式键入还有助于防止不明显的错误键入对象的传输,这些对象在代码中的路径中移动时,您没有考虑到它的类型是意外的。这类错误通常在程序经过大量测试后才变得清晰,更常见的是在程序发布后 它也有助于未来的程序员(包括你未来的自己)尝试使用你的代码,使他们更可能一目了然地知道对象应该是什么。因此,它使代码更加“自文档化” 有些东西

什么更好?为什么


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

显式键入提供了构建时保护,当您对可能不起作用的内容执行强制转换或执行操作时,会通知您可能出现的问题

显式键入还有助于防止不明显的错误键入对象的传输,这些对象在代码中的路径中移动时,您没有考虑到它的类型是意外的。这类错误通常在程序经过大量测试后才变得清晰,更常见的是在程序发布后

它也有助于未来的程序员(包括你未来的自己)尝试使用你的代码,使他们更可能一目了然地知道对象应该是什么。因此,它使代码更加“自文档化”

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


但是,绝大多数情况下,显式类型对您有利。

我不认为两者之间存在性能差异。 您可以让id为init返回type,因为您可以强制转换init的结果

例如:

Toto *foo = [[Toto alloc] init];
id foo2 = [[Toto alloc] init]; 
这两种方法都可以工作,但您必须像
(Toto*)foo
那样强制转换
foo2
变量,以便在不创建编译器警告的情况下访问实例的属性或方法。即使它很好用

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

问候,
KL94

什么更好?为什么

显式键入信息总是更好的,除非您出于某种原因无法使用它(见下文)

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

很久很久以前,API中的所有内容都使用了
id
。这被证明是一个彻头彻尾的痛苦;易碎,并导致了许多特定类型的碰撞

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

在以下情况下,什么更好 类init方法和常用的 代码中的变量

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

retain
objectAtIndex:
addObject:
和许多其他方法也是如此,它们获取或返回多种对象中的一种(或将它们作为参数)

而且,不,
id
和NSView*
之间绝对没有性能差异


你能举一个明确的例子吗 打字会引起问题吗

如果你写:

- (MyClass *) init;
在一个子类中:

- (MySubclass *) init;

您很可能会从wazoo中得到编译器警告,或者您必须键入wazoo。请尽可能使用特定的类型,但不能更具体。考虑如何使用任何特定的变量、参数或返回类型,并适当地设置其类型。

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

如果您的代码过于具体,那么您的代码就会变得不灵活,只接受严格意义上不必要的特定实现(即当您可以真正使用任何NSString时,要求使用NSMutableString)

如果您太模糊(例如,将所有内容都键入
id
),那么当您向特定实例发送无法识别的选择器时,您将无法识别,并且编译器无法识别任何数量的无效语句

对于
init
方法,请遵循中的建议

初始值设定项方法的返回类型应为id

这样做的原因是,id表示该类故意不被认为是未指定的,并且可能会根据调用的上下文进行更改。例如,NSString提供了initWithFormat:方法。但是,当发送到NSMutableString的实例(NSString的子类)时,消息返回的是NSMutableString的实例,而不是NSString。(但也请参见“组合分配和初始化”中给出的单例示例。)


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

请举例说明显式键入何时会导致问题?@Andrew我修改了我的答案,不留下那个模糊的“问题”字,并举例说明何时不能。谢谢你指出这一点。另请参见bbum的答案,以获得一个好的示例;生成的代码没有差别,即使是.yup。修正了语法和我的misd