开发者

objective c 2.0 - keyword casting vs non-keyword casting

I come from a C# background and I am learning Objective-C. I was wondering if I could get some clarification on syntax. Thanks in advance for your help.

What is the difference between the lines of code shown below? Given that I know for sure that the type in the "tempItem" dictionary is an (NSString *) type and newsItem.pictureUrl is also an (NSString *):

Scenario 1:

newsItem.pictureUrl = [tempItem objectForKey:@"picture"];

开发者_JAVA百科Scenario 2:

newsItem.pictureUrl = (NSString *)[tempItem objectForKey:@"picture"];


I know what you mean. I also started out preferring to cast, since it clearly shows what you are doing. But after a while, it gets terribly tedious and you learn to omit it.

The fact that there are no generics, and that the containers only store objects, is a bit of a bummer, especially if you come from a language with generics. It means you are constantly and explicitly converting between objects and simple types (e.g. between NSNumber and int) and that there is no way, except to query [object class], to ensure you only get an NSString or an exception you can handle.

But the cast will not make any difference. If the object returned is not an NSString, and you cast it to one, it will make no difference. The cast does no implicit type checking, nor a conversion. It merely reinterprets the return value.


Casting between object types can basically only affect two things:

  1. What warnings the compiler emits (e.g. "the class for this variable doesn't appear to have the method you're trying to call")

  2. What properties the object has and how they work (e.g. the equivalent getter for self.awesome might be [self awesome] or [self isAwesome])

It emphatically does not affect what kind of object you get. The static types at compile time are just hints for the compiler. If you cast an object to a type that it isn't, you're just lying to the compiler.

In that particular case, it doesn't have any effect at all. Some people do write code like that, but AFAIK that's just because they find it comforting to just act like they're using a statically typed language (even though Objective-C isn't).


There's no difference between the two lines of code; it's purely stylistic.

The method objectForKey: here returns an object of type id, which is a generic object pointer. In Objective-C, an id can be implicitly converted to any Objective-C object type without a cast. The following two lines are equivalent:

id someId = ...;
NSString *someString = someId;  // #1
NSString *someString = (NSString *)someId;  // #2

This is similar to how in C, a pointer of type void* can be implicitly converted to a pointer to any other type without a cast (that is also true of Objective-C, but void* pointers are discouraged in Objective-C; that is not true in C++).

As far as type safety goes, both are equivalently unsafe. If the runtime type of the object is in fact the type you're casting it to (whether the cast is explicit or implicit) or a subclass thereof, then everything will work as intended. If the runtime type is not what you're expecting, then most likely an NSException will be thrown with the common object does not response to selector error, due to calling a function that doesn't exist for that type. It's also possible you might crash with a segmentation fault due to accessing an ivar that doesn't exist or has an unexpected value (since the object really isn't that type).

If you're unsure of that object's runtime type, you should check its runtime type with the -class or -isKindOfClass: methods, and then only take action if it's a particular type. Prefer using-isKindOfClass:`, since that still works with subclasses, as opposed to comparing the class for exact equality with a particular class. For example:

id someId = ...;
if ([someId isKindOfClass:[NSString class])
{
    // It's an NSString
    NSString *someString = someId;
    // Do stuff with someString...
}


The type of an Objective-C instance is really only useful for determining the appropriate amount of memory to allocate for creation of the instance, and for static analysis (code completion, compilation etc). At run time the instances are all represented by id's and the actual type of the object means much less. This dynamic behavior is by design, and allows a great amount of flexibility when designing ObjC applications.

You will see very little typecasting in the typical ObjC program.


Casting is only really necessary when you want to have the compiler understand the type for a call, so that it doesn't give "may not respond" warnings.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜