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

——- 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值