Objective-C 【构造方法(重写、场景、自定义)、super】

———————————————————————————————————————————
super关键字的使用

#import

@interface Animal : NSObject
-(void)run;
-(void)eat;
//+(void)eat;
@end

@implementation Animal
-(void)run
{
    NSLog(@"Animal run!");
}
-(void)eat
{
    NSLog(@"-Animal eat!-");
}
//+(void)eat  //经过验证,super是不能指代父类 类对象 的,也就不能通过super来调用父类的类方法。
//{
//    NSLog(@"+Animal eat!+");
//}
@end

@interface Dog : Animal
-(void)run;
@end

@implementation Dog
-(void)run
{
    NSLog(@"Dog run!");
//    [super run];
//    [super eat];
}
@end

@interface BigYellowDog : Dog
-(void)run;
@end

@implementation BigYellowDog
-(void)run
{
    NSLog(@"BigYellowDog run!");
    [super run];//调用了父类的run方法(此时BigYellowDog的父类是Dog,Dog的父类是Animal,Dog和Animal中都有run方法,此时优先调用Dog的run方法),super指代父类Dog的实例对象。
    [super eat];//调用了父类的eat方法(此时Dog类中没有eat方法,而Animal类中有,那么就调用Animal中的eat方法),super指代Animal的实例对象,所以说super是可以指代 父类的父类 的实例对象的。
   
    //★super指代的是父类的实例对象。这句话要明白,因为run和eat都是对象方法,显然需要有对象来调用。故super指代的正是父类的实例对象。
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        BigYellowDog *byd=[[BigYellowDog alloc] init];
        [byd run];
    }
    return 0;
}


———————————————————————————————————————————
重写构造方法

#import

@interface Person : NSObject
{
    @public
    int _age;
}
@end

@implementation Person

//重写init方法,这样的话调用的时候子类覆盖了父类的init方法,就达到了重写的目的
- (instancetype)init
{
    self=[super init];//init是一个对象方法,返回值是instancetype类型(和id类型差不多)。这个地方要先将原父类的init方法调用一遍,也就是先用父类原有的init方法执行一遍。为什么还要这么做呢?那是因为父类在init的时候可能会初始化失败,也可能产生其他未知的初始化信息。为了不掩盖父类所做的事情,所以我们的原则是先让父类将原来要做的事情做完,然后做一个判断,如果父类init成功(即不为空),那么就开始执行重写的init方法
    if(self)//如果初始化成功
    {
        _age=10;//将实例对象的_age属性设置为10
    }
    return self;//最后返回这个对象(self指代的就是方法的调用者,也就是实例对象自身)
}
@end

@interface Student : Person
{
    @public
    int _sno;
}
@end

@implementation Student
-(instancetype)init
{
//    如果不写 self=[super init];  也就是不做父类的初始化,那么输出s->_age = 0  ,  s->_sno = 1  ,这是为什么呢?
//    显然Student是Person的子类,Person中我们重写了init方法,让实例对象初始化的_age属性值为10,而Student的init如果只写_sno=1,显然就覆盖掉了父类_age的初始化,那么就不会初始化_age属性,这样造成了初始化的部分遗失,所以说重写init构造方法时要遵守严格的程序:
    
//    ①先执行父类的init
    self=[super init];
//    ②判断self是否初始化成功
    if(self)
//    ③初始化当前类的实例变量
    {
    _sno=1;
    }
//    ④return self; 返回实例对象
    return self;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p1=[Person new];
        Person *p2=[[Person alloc] init];
        NSLog(@"p1->_age = %d\np2->_age = %d",p1->_age,p2->_age);
        NSLog(@"**************************************************");
        
        Student *s=[[Student alloc]init];
        NSLog(@"s->_age = %d\ns->_sno = %d",s->_age,s->_sno);
    }
    return 0;
}


———————————————————————————————————————————
重写构造方法的应用场景

#import

@interface Soldier : NSObject
@property Gun* gun;
-(void)fire;
@end

@implementation Soldier
//为Soldier类重写init方法,目的是每创建一个Soldier实例对象,就默认这个对象拥有一把枪,所以枪这个属性需要在初始化的时候附上
-(instancetype)init
{
    if(self=[super init])
    {
        Gun *gun=[[Gun alloc]init];
        _gun=gun;
    }
    return self;
}
-(void)fire
{
    [_gun shoot];
}
@end

@interface Gun : NSObject
@property int bulletCount;
-(void)shoot;
@end

@implementation Gun
//为Gun类重写init方法,目的是每创建一个Gun实例对象,就默认这个对象拥有3发子弹,所以子弹数目为3这个属性需要在初始化的时候附上
-(instancetype)init
{
    if(self=[super init])
    {
        _bulletCount=3;
    }
    return self;
}
-(void)shoot
{
    _bulletCount--;
    NSLog(@"shoot!!!!!!剩余子弹:%d",_bulletCount);
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        for (int i=0; i<20; i++) {
            Soldier *s=[[Soldier alloc]init];//创建了20个大兵,让他们一人一把专属的枪,然后每把枪都有三发子弹,然后射击三次
            [s fire];
            [s fire];
            [s fire];
        }
    }
    return 0;
}


———————————————————————————————————————————
自定义构造方法


//自定义构造方法:
//我们要以指定的值进行初始化,比如说,我们对学生这个类进行初始化,那么我们需要初始化学生的 姓名、年龄、学号 等。
//注意事项:
//①自定义构造方法是一个对象方法
//②返回值是 instancetype 类型(id)
//③方法名一定要以 initWithXXXXX 命名


#import

@interface Person : NSObject
@property NSString* name;
@property int age;
-(instancetype)initWithName:(NSString *)name andAge:(int)age;
@end

@implementation Person
-(instancetype)initWithName:(NSString *)name andAge:(int)age//我们的这些自定义的构造方法一定要在.h文件中声明
{
    if (self=[super init]) {
        _name=name;
        _age=age;
    }
    return self;
}
@end

@interface Student : Person
@property int sno;
-(instancetype)initWithName:(NSString *)name andAge:(int)age andSno:(int)sno;
@end

@implementation Student
-(instancetype)initWithName:(NSString *)name andAge:(int)age andSno:(int)sno
{
    if (self=[super initWithName:name andAge:age]) {
        _sno=sno;
    }
    return self;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Student *s=[[Student alloc]initWithName:@"wang" andAge:18 andSno:1];
        NSLog(@"name:%@,age:%d,sno:%d",s.name,s.age,s.sno);
    }
    return 0;
}


———————————————————————————————————————————

你可能感兴趣的:(构造方法,构造方法的重写,自定义构造方法,构造方法的场景,super关键字,OC)