0

Lets say I have made a Fraction class in Objective-C (as in the book "Programming with Objective-C"). One of the methods, add:, was first created like so:

//Fraction.h & most of Fraction.m left out for brevity's sake. -(Fraction *)add: (Fraction*) f { Fraction *result = [[Fraction alloc] init]; //Notice the dot-notation for the f-Fraction result.numerator = numerator * f.denominator + denominator * f.numerator; result.denominator = denominator * f.denominator; return result; } 

Then in one of the later exercises, it says change the return type and argument type to id & make it work. The dot-notation, as shown above doesn't work any more, so I changed it to this:

-(id)add: (id)f { Fraction *result = [[Fraction alloc] init]; result.numerator = numerator * [f denominator] + denominator * [f numerator]; // So forth and so on... return result; } 

Now my guess to why the dot-notation needs to be changed is because up until run-time, the program doesn't know what type of object that was passed to the add argument(f), therefore the compiler doesn't know of any accessor methods for f.

Am I anywhere close to understanding this? If not, can someone please clarify?

1
  • Even you can typecast id f to Fraction and use . Commented Mar 30, 2013 at 17:03

3 Answers 3

5

The dot syntax and properties actually have absolutely nothing to do with each other save for that they were introduced at the same time.

Properties are a convenience for defining accessors on a class while also adding the ability to specify atomicity policy and/or memory management policy.

Dot syntax is a convenience for accessing any accessor-like API on an object. The dot is not limited to use with properties; you can say myArray.length, for example.

When creating dot syntax, it was desired to limit the ambiguity as much as possible. Thus, it was specifically chosen that use of the dot would require that the object in the expression would be explicitly typed; that the id generic type would not be allowed.

The motivation was the number of times that Key-Value Coding type expressions had blown up in various programs. Since the dot is a sort of compiled KVC expression, the goal was to eliminate that fragility.


In general, the id type is to be avoided. This is further encouraged through the introduction of the instancetype keyword (totally unrelated to the original question, but of relevance to the discussion above).

Sign up to request clarification or add additional context in comments.

3 Comments

I still think that one should be able to use the dot syntax on ids. I'm writing a Bison grammar with Objective-C, and it would make the code much cleaner/clearer. :'(
@PauloTorrens While that would have made grammar creation easier, supporting parsers of the language was considered secondary to supporting the users of the language. ;)
@bburn Actually, parsers with the language. It's not an Objective-C parser, but it is written in it. Anyways... it makes some sense (for me, at least) that, for class types in general, even for NSObject, it raises a syntax error if the property or message isn't declared. But is there a reason why this can't be overlooked on id types, accepting any message after the dot? It could make the code cleaner in some cases to avoid the cast and still use the dot syntax when you're sure it would work on runtime (though I comprehend that coders would easely abuse this feature).
3

This is correct. The compiler can not determine the actual type of the object at compile-time and therefore can not determine whether denominator is a property. Changing it to use bracket syntax allows it to send denominator as a message to the object without needing to know the object type. The only thing required to get this to compile without error is the method -denominator being defined anywhere. As you can imagine, using id and avoiding type checking is dangerous as you may send messages to objects that do not implement that method, resulting in a runtime exception being raised.

EDIT: As bbum points out, denominator does not have to be a property and this is a general restriction over using dot syntax with objects using the id generic type.

7 Comments

I think the point of the exercise was to understand what was happening when you use the id data-type. I understand it probably isn't best practice to use over-use id - especially when you know the type the argument needs.
Almost correct; denominator does not have to be a property. In fact, properties and dot syntax have nothing to do with each other save for when they were introduced.
AFAIK foo.bar is the same as [foo bar] as far as the compiler is concerned, is this true or not?
Yes, that's true. Edited my post to add the note by bbum.
@11684 As long as foo is strongly typed and declares a method named notAsPropertyDeclaredBar, then you are correct. Josh is correct that an accessor can be aliased, but that would be no different than simply declaring peanutButter as a method (in his example) that returns jelly.
|
0

@bbum is right, to put it in simple words, if you have an object "obj" of type "id" and call a method with a dot-syntax like: obj.methodName, the compiler will check the type of "obj", and produce an error: "Property 'methodName' not found", whereas [obj methodName] would bypass the compiler check. Later on it might crash in runtime, for example if "methodName" is misspelled. See more examples in the article clarifying Objective C id type checking and other id behaviours.

Note that dot-syntax is limited to methods without arguments, so calls like [objc setStuff:123] would be unchecked.

Comments