B.8.5 消息表达式
格式1:
[receiver name1:arg1 name 2:arg2,name3:arg3..]
这个格式调用由receiver指定的类中的方法name1:name2:name3……,并传递arg1、arg2……作为方法的参数。这种形式称为消息表达式。表达式的值是该方法返回的值,或如果方法是这样声明的,并且没有返回值,则表达式的值是void。表达式的类型就是被调用的方法所声明的类型。
格式2:
[receiver name];
如果方法不接收参数,那么这种格式用于从接收者指定的类调用方法名。
如果receiver是id类型,编译器将在声明的类中查找特定方法的定义或者继承来的定义。如果没有找到这样的定义,编译器就会发出一条警告,即接收者可能不会响应特定的消息。进一步假设:这个方法返回一个id类型的值,同时将所有浮点型参数转换成双精度类型并对所有整型参数进行整型提升,如同前面在“基本数据类型的转换”一节中所概述的那样。其他的方法参数在被传递时则不会进行类型转换。
如果receiver是一个class对象(可以仅仅通过指定类名来创建这个对象),则会调用特定的class方法。否则,receiver将是某个类的一个实例,并会调用对应的实例方法。
如果receiver是一个静态类型的变量或表达式,编译器就会在类定义中查找该方法(或者查找任何继承来的方法),并转换所有(可能位置处的)参数使之与方法期望的参数匹配。因此,给一个期望接受浮点值的方法传递整数会使这个整数在此方法被调用时自动转换为浮点值。
如果receiver是一个空对象指针(即nil),便可以向它发送消息。如果与该消息相关的方法返回一个对象,则消息表达式的值将为nil。如果方法不返回对象,表达式的值将是不确定的。
如果在多个类中定义同一个方法(既可显式地定义也可通过继承定义),编译器就会在各个类中检查参数和返回类型的一致性。
给方法传递的所有参数都是通过值传递的;因此,方法不能更改它们的值。如果给方法传递一个指针,方法就可以更改指针引用的值,但它仍然不能更改指针本身的值。
格式3:
receiver.property
这个格式会调用receiver的取值方法(默认为property),除非将该表达式用作左值(参见格式4)。可以使用@property指令更改取值方法名,此时将使用被调用的方法。
如果使用默认的取值方法名,那么前面的表达式等效于以下表达式:
[receiver property]
格式4:
receiver.property=expression
这个格式会调用与属性property相关联的赋值方法,将expression的值作为参数传递给它。默认情况下,会调用赋值方法setProperty:,除非使用了以前的@property指令为属性赋予了其他的赋值方法名。
如果使用默认的赋值属性名,那么前面的表达式等效于以下表达式:
[receiver setProperty:expression]