简体   繁体   中英

Why does [NSLocale currentLocale] return id?

In the header for NSLocale, currentLocale is declared like this:

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

It's obvious that they are returning id on purpose, but I'm curious why that would be necessary. Could this method ever return anything other than an NSLocale instance?

Back in the day, one used NSDictionary objects for locale information. See, for example, the "Special Considerations" documented for -[NSString compare:options:range:locale:] :

Special Considerations

Prior to OS X v10.5, the locale argument was an instance of NSDictionary . On OS X v10.5 and later, if you pass an instance of NSDictionary the current locale is used instead.

Some methods, such as -[NSDate dateWithNaturalLanguageString:locale:] still take an NSDictionary .

Other methods, such as many classes' -descriptionWithLocale: , can take either.

Anyway, with the introduction of NSLocale the types of various locale parameters was generalized to id to accommodate either kind of object without breaking source compatibility. The return type of +[NSLocale currentLocale] is similar generic so that it can be passed to methods that used to only take NSDictionary objects.

Initializers (even convenience initializer) traditionally return id . This prevents problems when you subclass. For instance, imagine this scenario:

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

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

This would be a compiler error. You are redefining initWithBar: to return a different type. But if you always return Foo* , then Baz *baz = [Baz initWithBar:bar] would fail because initWithBar: returns a superclass.

To get yourself out of this problem, all initializers have historically returned id if there's any chance the class will be subclassed (which is to say, you should really always do this).

Recently, clang added instancetype , which solves this problem more elegantly by representing "the type of the current class." This is only useable in the interface. You can't declare variables to be of type instancetype (I've actually wanted this in some cases…) id is automatically promoted to instancetype for methods that begin with init… . Otherwise, you need to use it manually. Many older Cocoa interfaces haven't been updated yet, but they're slowly moving over to instancetype .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM