【发布时间】:2011-01-14 01:32:52
【问题描述】:
我在目标 c 上观看此视频。这家伙展示了一个带有多个参数的方法,它看起来像这样
- (void) setTo: (int) n over: (int) d
{ .... }
他展示了使用它:
[myFraction setTo: 100 over:200];
括号表示法在点表示法中的外观如何?我不明白那是什么 意思是,有人知道吗?谢谢
【问题讨论】:
标签: objective-c
我在目标 c 上观看此视频。这家伙展示了一个带有多个参数的方法,它看起来像这样
- (void) setTo: (int) n over: (int) d
{ .... }
他展示了使用它:
[myFraction setTo: 100 over:200];
括号表示法在点表示法中的外观如何?我不明白那是什么 意思是,有人知道吗?谢谢
【问题讨论】:
标签: objective-c
[myFraction numerator]
可以写成
myFraction.numerator
但您也可以分配诸如
之类的值instance.property = value
但您不能以点表示法传递多个参数。
【讨论】:
在Objective-C中,我们可以在中间中为方法命名。因此,当他写[myFraction setTo:100 over:200]; 时,over 可能意味着……好吧,无论他想要什么。这是他选择的方法名称的一部分。在这种情况下,他可能试图让这种方法听起来像英语。 (“将此分数设置为 100 超过 200。”我们在正常语音中经常将分数读作“分子超过分母”。)
我们经常编写一些称为“访问器”的方法:这些是- (int)variable(称为“getters”)和- (void)setVariable:(int)newValue(称为“setters”)形式的方法。我这里的示例假定分别返回或更改名为variable 的实例变量。以下是方法实现的样子:
- (int)variable
{
return variable;
}
- (void)setVariable:(int)newValue
{
variable = newValue;
}
对于你的类的几乎每个实例变量都有这样的访问器是很常见的。在某些时候,有人厌倦了写 [myInstance setVariable:20]; 之类的东西,并决定他们宁愿它看起来像许多其他语言一样,myInstance.variable = 20;。
因此,Objective-C 2.0 添加了点表示法,它允许您编写...
myInstance.variable,在大多数情况下完全等同于[myInstance variable](并且不直接访问实例变量variable!),并且...
特例myInstance.variable = 20;,完全等价于[myInstance setVariable:20];。再次注意,这不会直接访问variable,它会向myInstance 发送消息。因此,如果我们在 setVariable 中编写了一些其他代码,如果我们使用点符号,它仍然可以访问。
点表示法设计用于访问器。理论上,您也可以将它用于任何返回值且不带参数的方法(例如myArray.count)。将它用于其他任何事情 (myInstance.doSomeAction) 的风格非常很差。不要这样做。因此,我相信您现在可以猜到,[myFraction setTo:100 over:200] 没有等效的点表示法,因为它需要 2 个参数,并且不是访问器。
【讨论】:
over: 是方法名称的一部分。 setTo(int n, int d) 不是一个很好的类似 C 函数。 setTo_over_(int n, int d) 更好。有问题的方法的全名不是setTo,而是setTo:over:。参数恰好在方法的中间。
点表示法是仅用于属性访问的简写表示法。编译器将其转换为适当的 setter/getter 方法调用。它只是语法糖。
所以给定这个属性访问使用点符号:
myFraction.numerator=100;
编译器将其替换为以下等效代码:
[myFraction setNumerator:100]
现在应该清楚为什么不能使用点表示法向对象发送普通消息了。我什至想不出它应该是什么样子。
关于点与括号符号的讨论很多。反对点符号的论据之一是它特别是对初学者产生的混淆。其他语言当然也使用属性访问器的方法,但是它们比 Objective-C 更一致地隐藏了这一事实。
【讨论】:
@property 意义上的“属性”,还是更一般的意义上的“属性”,但请注意,点表示法与手写访问器配合得很好(即使@ 987654324@ 从未在 .h) 中声明。如果你愿意的话,我什至会说,对myArray.count 之类的东西使用点符号并不是一种糟糕的风格。
您不能使用点符号传递多个参数。可通过点表示法使用的 setter 必须具有原型
-(void)setXxxx:(type)value;
但是,您可以创建一个辅助结构来将所有参数组合为一个:
struct Fraction { int n, d; };
struct Fraction MakeFraction(int n, int d) {
struct Fraction r;
r.n = n;
r.d = d;
return r;
}
...
-(void)setValue:(struct Fraction)f { ... }
...
myFraction.value = MakeFraction(100, 200);
(和 a “超过”b 表示 a / b。)
【讨论】:
从外观上看,这个方法是设置对象的两个实例变量/属性,分子(n)和分母(d)。除非你将它分成两个调用,否则你不能使用点符号来做到这一点:
myFraction.numerator=100;
myFraction.denominator=200;
请注意,点表示法仅用于访问实例变量/属性,不能替代消息发送。
【讨论】:
myFraction.numerator = 100 与 [myFraction setNumerator:100] 完全相同。