需要澄清Objective-C中的id数据类型

时间:2013-03-30 17:00:10

标签: objective-c syntax

假设我已经在Objective-C中创建了一个Fraction类(如“使用Objective-C编程”一书)。其中一个方法是添加:,首先是这样创建的:

//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;
}

然后在后面的一个练习中,它将返回类型和参数类型更改为id&让它起作用。如上所示,点符号不再起作用,所以我将其更改为:

-(id)add: (id)f {
    Fraction *result = [[Fraction alloc] init];

    result.numerator = numerator * [f denominator] + denominator * [f numerator];
    // So forth and so on...
    return result;
}

现在我想为什么点符号需要更改是因为直到运行时,程序不知道传递给add参数(f)的对象类型,因此编译器没有'知道f。

的任何访问方法

我是否接近理解这一点?如果没有,有人可以澄清一下吗?

3 个答案:

答案 0 :(得分:5)

点语法和属性实际上完全没有任何关系,除非它们是同时引入的。

属性可以方便地定义类的访问器,同时还可以添加指定原子性策略和/或内存管理策略的功能。

Dot语法可以方便地访问对象上任何类似访问器的API。点不限于与属性一起使用;例如,你可以说myArray.length

创建点语法时,希望尽可能地限制歧义。因此,特别选择使用点将要求表达式中的对象将被明确键入;

动机是键值编码类型表达式在各种程序中被炸毁的次数。由于点是一种编译的KVC表达式,因此目标是消除这种脆弱性。


通常,应避免使用id类型。通过引入id关键字(与原始问题完全无关,但与上述讨论相关),进一步鼓励了这一点。

答案 1 :(得分:4)

这是对的。编译器无法在编译时确定对象的实际类型,因此无法确定denominator是否为属性。将其更改为使用括号语法允许它将denominator作为消息发送到对象,而无需知道对象类型。要使其无错误地编译所需的唯一方法是在任何地方定义的方法-denominator 。可以想象,使用id并避免类型检查是危险的,因为您可能会向未实现该方法的对象发送消息,从而导致引发运行时异常。

编辑:作为bbum points outdenominator不一定是属性,这是使用id对象使用点语法的一般限制通用类型。

答案 2 :(得分:0)

@bbum是对的,用简单的话说,如果你有一个对象" obj"类型" id"并使用点语法调用方法,如:obj.methodName,编译器将检查" obj"的类型,并产生错误:"Property 'methodName' not found",而[obj methodName]会绕过编译器检查。稍后它可能会在运行时崩溃,例如,如果" methodName"拼写错误。请参阅澄清Objective C id type checking和其他ID行为的文章中的更多示例。

请注意,点语法仅限于没有参数的方法,因此将取消选中[objc setStuff:123]之类的调用。