黑马程序员——Objective-C学习笔记(三):组合

来源:互联网 发布:美图秀秀mac官方 编辑:程序博客网 时间:2024/05/19 16:04

——- android培训、IOS培训、期待与您交流! ———-

继承是在两个类之间之间建立关系的一种方式,它可以避免许多重复的代码。组合可以联合多个对象,让它们分工合作。在实际程序中,会同时用到继承和组合。

什么是组合

在Objective-C中,组合是通过包含作为实例变量的对象指针实现的。 以一个Pedal对象和一个Tire对象组合出一个虚构的Unicycle为例。Unicycle应该拥有一个指向Pedal对象的指针和一个指向Tire对象的指针。

@interface Unicycle : NSObject{    Pedal *pedal;    Tire *tire;}@end // Unicycle

PedalTire通过组合的方式构成了Unicycle

Car程序

假设一辆汽车只需要1台发电机和4个轮胎。以此搭建一个简单的汽车模型。

首先定义Tire类:

#import <Foundation/Foundation.h>@interface Tire : NSObject@end // Tire@implementation Tire// 如果类中没有包含任何实例变量,可以省略接口定义中的花括号- (NSString *) description{    return (@"I am a tire. I last a while.");} // description@end // Tire
// Engine类@interface Engine : NSObject@end // Engine@implementation Engine- (NSString *) description{    return(@"I am an engine.");} // description@end Engine
// Car类@interface Car : NSObject{    engine *engine;    Tire *tire[4];}- (void) print;@end //Car@implementation Car- (id) init{// 调用[super init]让超类完成初始化工作,init方法返回的值(id类型的数据,泛型对象指针)就是被初始化的对象。// 将[super init]返回的值赋给self是为了防止超类在初始化过程中返回的对象与一开始创建的不一致。    if (self = [super init])    {        engine = [Engine new];        tires[0] = [Tire new];        tires[1] = [Tire new];        tires[2] = [Tire new];        tires[3] = [Tire new];    }    return (self);} // init- (void) print{    NSLog(@"%@", engine);    NSLog(@"%@", tires[0]);    NSLog(@"%@", tires[1]);    NSLog(@"%@", tires[2]);    NSLog(@"%@", tires[3]);} // print@end // Car

每个Car对象都会为指向enginetires的指针分配内存,但是真正包含在Car中的并不是enginetires变量,只是内存中的其他对象的引用指针。为新建的Car对象分配内存时,这些指针将被初始化为nil
print方法通过NSLog()输出实例变量。%@调用每个对象的description方法并显示结果。

// main函数创建新对象*Car*,并告诉它输出自身信息,然后推出程序。int main(int argc,const char *argv[]){    Car *car;    car = [Car new];    [car print];    return 0;} // main

属性的存取方法

存取方法用来读取或改变某个对象的属性。 给变量赋值的称为setter方法,访问对象属性的称为getter方法。

下面为Car类添加settergetter方法。

首先设置接口:

@interface Car : NSObject{    Engine *engine;    Tire *tires[4];}- (Engine *) engine; // 访问engine的属性- (void) setEngine : (Engine *) newEngine; // 设置engine的属性- (Tire *) tireAtindex : (int) index; // 访问tire的属性- (void) setTire : (Tire *) tire atIndex : (int) index; // s设置tire的属性- (void) print;@end // Car

Cocoa对存取方法的命名惯例

setter方法根据它所更改的属性的名称来命名,并加上前缀set
getter方法则是以其返回的属性的名称来命名。不要将get作为getter方法的前缀。

get这个词在Cocoa中有特殊含义。如果get出现在Cocoa的方法名称中,暗示这个方法会将你传递的参数作为指针来返回数值。

// engine方法的实现@implementation Car// getter方法engine返回实例变量engine的当前值。// 在Objective-C中所有对象间的交互都是通过指针实现的,所以方法engine返回的是一个指针,指向Car中的engine对象。- (Engine *) engine{    return (engine);} // engine// setter方法setEngine : 将实例变量engine的值赋为参数所指向的值,实际被复制的不是engine变量,而是指向engine的指针值。- (void) setEngine : (Engine *) newEngine{    engine = newEngine;} // setEngine// tires属性的存取方法- (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:@end // Car

更新main函数如下,采用存取方法初始化car对象:

int main  (int argc,const char *argv[]){    Car *car = [Car new];    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

利用存取方法扩展程序

// 创建新engine子类slant6@interface Slant6 : Engine@end // Slant6@implementation Slant6- (NSString *) description{    return (@"I am a slamt-6.OOOOM!!!!");} // description@end // Slant6// 创建新Tire子类AllWeatherRadial@interface AllWeatherRadial : Tire@end // AllWeatherRadial@implementation AllWeatherRadial- (NSString *) description{    return (@"I am a tire for rain or shine.");} // description@end // AllWeatherRadial

调整一下main函数,使用enginetire的子类:

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