OC中的继承与复合

处理类和对象的关系时,尤其要重视OOP的两个方面:

    第一个方面是继承,创建一个新类时,通常需要根据它与现有的类的区别来定义,使用继承可以定义一个具有父类所有功能的新类;

    第二个方面是复合,也就是在对象中可以再引用其他对象。


继承的语法格式


    在创建新类时,冒号后面的标识符是需要继承的类。早OC中,你可以选择不继承,但如果你使用的是Cocoa框架,就需要继承NSObject类,因为它提供了大量有用的特性。

    有些编程语言具有多继承性,也就是一个类可以继承多个类,但是OC不支持多继承,只能继承一个。


继承的工作机制


1)当代码发送消息时,OC的方法调度机制将在当前的类中搜索相应的方法。如果无法在接受消息的对象的类文件中找到相应的方法,它就会在该对象的超类中进行查找。

2)在创建一个新类时,其对象首先会从它的超类继承实例变量,然后根据自身情况天假自己的实例变量。

3)在你制作全新的子类时,经常会添加自己的方法。有时你会添加一个能够向类中引入特有功能的新方法,有时你会替换或改进某个超类定义的现有方法。


self和super


1)在OC中,关键字self与c++中this是同一概念,就是类对象自身的地址,通过self可以调用自己的实例变量和方法。

2)当子类需要调用父类的方法时,会用到Super关键字. Super指向的是父类的指针,子类重写父类的方法时,调用父类的方法是一个比较好的习惯。因为当我们不知道父类在该方法中实现的功能时,如果不调用父类的方法,有可能我们重写的方法会失去该功能,这是我们不愿意看到的情况。

3)当使用self调用方法时,会从当前类的方法列表中开始寻找,如果没有,就从父类中再找,而使用super时,则从父类的方法列表中开始找,然后调用父类的这个方法

@interface PersonSelf : NSObject
{
    
    //声明两个实例变量
    int age;
    NSString * name;
    Student *s;
}

//定义方法
-(NSString *) getName;
-(void) setName:(NSString *)_name;
-(int) getAge;
-(void)setAge:(int)_age;
@end
@implementation PersonSelf
-(id)init{
/*为了让超类(在这里时NSObject)将所有需要的初始化工作一次性完成,你需要调用[super init]。init方法返回的值(id类型数据,即泛型对象指针)就是被初始化的对象。将[super init]返回的结果付给self是OC的惯例。这么做是为了防止超类在初始化过程中返回的对象与一开始创建的不一致。*/
  if(self=[super init]){  //super可以调用父类中的方法
        s=[[Student alloc]init];
        NSLog(@"student:%@\n",s);
    }
    return  self;
}
-(NSString *) getName{
    return  name;
}
-(void) setName:(NSString *)_name{
    name=_name;
    [self setAge:14];//self可以去调用本类对象中的方法
    NSLog(@"setAge");
    NSLog(@"self class is: %@\n",[self class]);
    NSLog(@"super class is: %@\n",[super superclass]);
    
}
-(int) getAge{
    return  age;
}
-(void)setAge:(int)_age{
    age=_age;
}
@end



 

复合

@interface Tire : NSObject
@end
//如果在类中没有包含任何实例变量,便可以省略掉接口定义中的花括号。
@implementation Tire
-(NSString*)description{
    return (@"I am a tire.I last a while.");
}
@end

@interface Engine : NSObject
@end

@implementation Engine
-(NSString*)description
{
    return (@"I am an engine,Vroom!");
}
@end
/*Engine和Tire通过复合的方式组成了Car.
每一个Car对象都会为engine和tires的指针分配内存,但真正包含在Car中的并不是engine和tires变量,只是内存中存在的其他对象的引用指针。
使用new创建新对象时,系统其实在后台执行了两个步骤:
第一步,为对象分配内存,即对象获得一个用来存放实例变量的内存块;
第二步,自动调用init方法,使该对象进入可用状态。*/
@interface Car : NSObject
{
    Engine *engine;
    Tire *tires[4];
}
-(void)print;
@end
@implementation Car

-(id)init
{
    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;
}
-(void)print
{
    NSLog(@"%@",engine);
    NSLog(@"%@",tires[0]);
    NSLog(@"%@",tires[1]);
    NSLog(@"%@",tires[2]);
    NSLog(@"%@",tires[3]);
}
@end
int main(int argc, const char * argv[]) {

    Car *car;
    car = [Car new];
    [car print];
    return 0;
}


继承的类之间建立的关系是"is a"(是一个);

复合的类之间建立的关系是"has a"(有一个)。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值