在NSLocale的标题中,currentLocale
声明如下:
+ (id /* NSLocale * */)currentLocale; // an object representing the user's current locale
显然他们故意回归id
,但我很好奇为什么这是必要的。这个方法可以返回NSLocale实例以外的任何东西吗?
答案 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…
。