为什么[NSLocale currentLocale]返回id?

时间:2013-10-10 16:24:55

标签: objective-c cocoa

在NSLocale的标题中,currentLocale声明如下:

+ (id /* NSLocale * */)currentLocale;   // an object representing the user's current locale

显然他们故意回归id,但我很好奇为什么这是必要的。这个方法可以返回NSLocale实例以外的任何东西吗?

2 个答案:

答案 0 :(得分:4)

在当天,人们使用NSDictionary个对象来获取区域设置信息。例如,请参阅-[NSString compare:options:range:locale:]记录的“特殊注意事项”:

  

特别注意事项

     

在OS X v10.5之前, locale 参数是NSDictionary的实例。在OS X v10.5及更高版本中,如果传递NSDictionary的实例,则使用当前的语言环境。

某些方法(例如-[NSDate dateWithNaturalLanguageString:locale:])仍采用NSDictionary

其他方法,例如许多类“-descriptionWithLocale:”也可以采用。

无论如何,随着NSLocale的引入,各种语言环境参数的类型被推广到id以适应任何类型的对象而不会破坏源兼容性。 +[NSLocale currentLocale]的返回类型类似于泛型,因此可以将其传递给过去只使用NSDictionary个对象的方法。

答案 1 :(得分:2)

初始化器(甚至是便利初始化器)传统上返回id。这可以防止子类时出现问题。例如,想象一下这种情况:

@interface Foo : NSObject
- (Foo *)initWithBar:(Bar *)bar;
@end

@interface Baz : Foo
- (Baz *)initWithBar:(Bar *)bar;
@end

这将是编译器错误。您正在重新定义initWithBar:以返回其他类型。但是如果你总是返回Foo*,那么Baz *baz = [Baz initWithBar:bar]会失败,因为initWithBar:会返回一个超类。

为了摆脱这个问题,所有初始化程序在历史上都返回id,如果该类有可能被子类化(也就是说,你应该总是这样做)。

最近,clang添加了instancetype,它通过表示“当前类的类型”更加优雅地解决了这个问题。这仅适用于界面。您不能将变量声明为instancetype类型(我在某些情况下实际上想要这个...)id会自动提升为instancetype以查找以{{1}开头的方法}。否则,您需要手动使用它。许多旧的Cocoa接口尚未更新,但它们正在慢慢转移到init…