2011-01-06 81 views
4

以下是一些苹果类的几种方法:当一个方法可以返回子类时返回类型应该是什么?

- (NSManagedObject *)objectWithID:(NSManagedObjectID *)objectID; 
- (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier; 

+ (id)insertNewObjectForEntityForName:(NSString *)entityName inManagedObjectContext:(NSManagedObjectContext *)context 

这是合理的预期,所有这些方法返回的返回类型的子类。由于这个原因,返回的对象通常被分配给一个预期类型的​​变量,例如:

BCCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[BCCustomTableViewCell cellIdentifier]]; 

这使得编译器不高兴;铸造解决了这一点,但铸造这样脏:

BCCustomTableViewCell *cell = (id)[tableView dequeueReusableCellWithIdentifier:[BCCustomTableViewCell cellIdentifier]]; 

然而,当返回类型是id,这个转换可以被删除,尽管某些类型的安全成本,导致我的代码是清洁:

BCPerson *person = [NSEntityDescription insertNewObjectForEntityForName:BCPersonEntityName inManagedObjectContext:context]; 

就我个人而言,我更喜欢当返回类型为id。苹果是否有任何理由选择其中一种方法,还是仅仅是由于开发人员偏好编写这些方法?

+0

铸造是肮脏的,但有方法返回`ID`脏! – 2011-01-06 11:39:00

回答

4

在你描述的三个例子,两种不同原理在起作用:

在两个第一,苹果希望你使用强制转换为“我知道我在做什么”之类的事情:当你通过一个标识符访问一个通用对象,除非你知道你在做什么,否则你最终会被返回值的类感到惊讶。

在后面的例子中,该方法本质上是一种工厂方法,相当于alloc init,在大多数情况下,您最好知道自己在做什么。

换句话说,回答你的问题:

对于一个工厂方法,id,对于一个getter,一样的二传手。

2

我真的很喜欢铸造。如果您从这些方法返回id,编译器根本不会警告您,因为它无法知道将在那里返回的内容。如果您正确投入返回值(而不是转换为id),那么您可以确定,如果您没有收到警告,则表明您做得对。所需要的就是多写一个类名。

BCCustomTableViewCell *cell = (BCCustomTableViewCell *)[tableView dequeue...]; 

没有返回id的理由是,你不回只是什么,但给定类及其子类。从这个例子的方法,你总是得到一个表格视图单元格,你可以依靠它响应某些方法(除非你搞砸你的子类,这是)。如果你返回id你不能依赖任何东西,再加上编译器不会警告你。

编辑: 我只是指的是实例方法,而不是类方法。 Williham解释了这种差异。

+1

我同意。方法定义应该尽可能保守,以便给编译器提供最好的机会在你做一些愚蠢的事情时发出警告。责任应该在程序员身上,通过演员表明他们知道自己在做什么(或不是!)。 – 2011-01-06 11:37:45

1

如果返回类型是id那么方法定义肯定不太有用吗?您可以接收任何类型的对象,并且可能没有编译时类型检查。

最后,设置一个子类对象只会导致编译器警告,这是由于错字造成的潜在错误或错误阅读文档的首选情况。

1

铸件脏,但方法返回id更肮脏,因为可能存在潜伏在下面的隐患,编译器无法警告您。做演员只是向编辑说'你已经警告过我,现在让我面对危险'。

相关问题