热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

ObjectiveC复合(Compostion)——存取方法

0x01存取方法是间接的一个例子上一篇中,我们已经构造了一台“车”。假设现在我想要随时更换自己喜欢的发动机和轮胎,就要用到“存取方法”。“存取方法

0x01 存取方法是间接的一个例子

上一篇中,我们已经构造了一台“车”。

假设现在我想要随时更换自己喜欢的发动机和轮胎,就要用到“存取方法”。

“存取方法”是用来读取或改变某个对象属性的方法,例如此前见过的setFillColor:就是一个存取方法。

如果我们要对其他对象中的属性进行操作,应该尽量使用对象提供的存取方法,绝对不要直接改变对象里面的值,而应该使用setter方法进行更改。

正确使用“存取方法”将会使程序更加灵活。



0x02 方法的命名规则

1、虽然说方法的命名是自由的,但为了程序的可读性,我们还是应该遵循Cocoa的惯例:

setter方法应根据它所要更改的属性名称来命名,如“set+属性名”;

getter方法只需以其返回的属性名命名即可,即“属性名”。

因为get这个词在Cocoa中有特殊含义,如果get出现在Cocoa的方法名称中,就意味着这个方法会将传递给它的参数作为指针来返回数值。


2、setter方法和getter方法一般是成对出现的,当然也可以不成对出现。如对于只读特性只有getter方法,对于密码特性只有setter方法。



0x03 存取方法的实现


我们先在Car的接口中对添加的setter和getter方法进行声明:

@interface Car : NSObject
{Engine *engine;Tire *tires[4];
}//New Code
- (Engine *) engine;
- (void) setEngine: (Engine *) newEngine;
- (Tire *) tireAtIndex: (int) index;
- (void) setTire: (Tire *) tire atIndex: (int) index;
//New Code- (void) print;
@end // Car


第一对存取方法是为了访问发动机的属性:

- (Engine *) engine;
- (void) setEngine: (Engine *) newEngine;

调用Car对象的engine方法可以访问engine变量,调用setEngine:方法可以更改发动机属性。

下面是这两个方法的实现:

- (Engine *) engine
{return (engine);
} // engine
- (void) setEngine: (Engine *) newEngine
{engine = newEngine;
} // setEngine

我们看到getter方法engine返回的是一个指针,指向Car中的Engine对象。实际上是返回实例变量engine的当前值;

同样的,setter方法setEngine:将newEngine的值赋给engine实例变量。实际上被修改的是engine的指针值。

在Objective-C中所有对象间的交互都是通过指针实现的!


第二对存取方法是为了访问轮胎的属性:

- (void) setTire: (Tire *) tire atIndex: (int) index;
- (Tire *) tireAtIndex: (int) index;


由于汽车的4个轮胎处于4个位置,所以Car对象中必须包含一个表示轮胎位置的数组:

- (void) setTire: (Tire *) tire atIndex: (int) index{if (index <0 || index > 3) {NSLog (@"bad index (%d) in setTire:atIndex:",index);exit (1);
}tires[index] = tire;
} // setTire:atIndex:
- (Tire *) tireAtIndex: (int) index
{if (index <0 || index > 3) {NSLog (@"bad index (%d) in "tireAtIndex:", index);exit (1);
}return (tires[index]);
} // tireAtIndex:

因为tire是一个C风格的数组,对于其索引值是否有效,编译器是可能直接忽略的。所以我们自己得用if条件语句来判断index值是否合理,这是一种防御式编程思想

setTire:方法的声明格式看起来不太一样,这是因为它拥有两个参数,往后学习会更加理解这种写法。


最后修改main()函数:

int main (int argc, const char * argv[]) {Car *car = [Car new];//事实上可以在Car类中把init方法删掉,因为下面的代码已经做了init方法的工作Engine *engine = [Engine new];[car setEngine: engine];for (int i = 0; i <4; i++) {Tire *tire = [Tire new];[car setTire: tire atIndex: i];}[car print];return (0);
} // main

程序运行结果没有变化,但我们改进了它的内部结构,使程序更加灵活:

I am an engine. Vrooom!
I am a tire. I last a while.
I am a tire. I last a while.
I am a tire. I last a while.
I am a tire. I last a while.



0x04 存取方法的应用

我们已经为Car类添加了存取方法,那换配置就是随心所欲的事了。

现在来为这台车换一个发动机:

@interface Slant6 : Engine
@end // Slant6@implementation Slant6
- (NSString *) description
{return (@"I am a slant- 6. VROOOM!");
} // description
@end // Slant6

创建这台Slant6发动机,继承了Engine超类的属性。但是重写了description方法,输出了新发动机的信息。


接着我们换轮胎:

@interface AllWeatherRadial : Tire
@end // AllWeatherRadial@implementation AllWeatherRadial
- (NSString *) description
{return (@"I am a tire for rain or shine.");
} // description
@end // AllWeatherRadial


最后修改main()函数,这台车使用了全新的发动机和轮胎:

int main (int argc, const char * argv[]) {Car *car = [Car new];for (int i = 0; i <4; i++)
{//New CodeTire *tire = [AllWeatherRadial new];//New Code[car setTire: tire atIndex: i];}//New CodeEngine *engine = [Slant6 new];//New Code[car setEngine: engine];[car print];return (0);
} // main

运行程序后,可以发现输出已经更新为新配置了:

I am a slant- 6. VROOOM!
I am a tire for rain or shine.
I am a tire for rain or shine.
I am a tire for rain or shine.
I am a tire for rain or shine.





推荐阅读
author-avatar
小小伟
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有