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?

4

3 回答 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).

于 2013-03-30T17:15:46.517 回答
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.

于 2013-03-30T17:09:54.380 回答
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.

于 2016-04-29T21:19:53.447 回答