假设我已经在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。
的任何访问方法我是否接近理解这一点?如果没有,有人可以澄清一下吗?
答案 0 :(得分:5)
点语法和属性实际上完全没有任何关系,除非它们是同时引入的。
属性可以方便地定义类的访问器,同时还可以添加指定原子性策略和/或内存管理策略的功能。
Dot语法可以方便地访问对象上任何类似访问器的API。点不限于与属性一起使用;例如,你可以说myArray.length
。
创建点语法时,希望尽可能地限制歧义。因此,特别选择使用点将要求表达式中的对象将被明确键入; 1}}泛型类型将不被允许。
动机是键值编码类型表达式在各种程序中被炸毁的次数。由于点是一种编译的KVC表达式,因此目标是消除这种脆弱性。
通常,应避免使用id
类型。通过引入id
关键字(与原始问题完全无关,但与上述讨论相关),进一步鼓励了这一点。
答案 1 :(得分:4)
这是对的。编译器无法在编译时确定对象的实际类型,因此无法确定denominator
是否为属性。将其更改为使用括号语法允许它将denominator
作为消息发送到对象,而无需知道对象类型。要使其无错误地编译所需的唯一方法是在任何地方定义的方法-denominator
。可以想象,使用id
并避免类型检查是危险的,因为您可能会向未实现该方法的对象发送消息,从而导致引发运行时异常。
编辑:作为bbum points out,denominator
不一定是属性,这是使用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]
之类的调用。