• 对象的alloc+init

类对象的new方法可以创建一个属性均为0的对象

new方法实际上是两个方法的连续调用:

     1)分配存储空间 alloc 类对象方法

     2)初始化 init 对象方法

也就是说 Person *p = [Person new]; 等同于: Person *p = [[Person alloc] init];


alloc和init方法都是NSObject的方法,故所有的OC类型都可以使用这种方式创建对象

init方法:

- (instancetype)init

     该方法的默认操作:调用父类的init方法,并返回对象本身,成员变量的初值为0


  • 重写init方法

默认的init方法,将对象的属性初值设为0,如果我们想要指定一个初值,就需要重写该方法。

NSObject的子类重写init方法的步骤:

    1. 调用父类的init方法,将其父类中的属性初始化

    2. 为子类的属性初始化

    3. 返回对象本身

重写init方法一般形式:

如:Person类,包含一个属性_age

- (instancetype)  init
{
    if ( self = [super init] ) {
        _age = 10;
    }
    return self;
}

再如:Person的子类Student,包含一个属性score

-  (instancetype) init
{
    if ( self = [super init] ) {//调用了父类Person的init函数
        _score =  1;
    }
    return self
}

init方法是一层一层往下调用的

     重写构造方法的目的是为了对象创建出来,成员变量就会有一些规定的值

     Objective-C(6)对象的构造


  • 自定义init方法

默认的Init方法不带参数,只能为对象初始化一些固定值

通过自定义init方法可以实现通过参数初始化对象属性。

     返回值一般是instancetype类型

     方法名以initWith开头

如Person类中包含属性name和age

- (instancetype) initWithName:(NSString *) name {
    if ( self = [super init] ) {
        _name = name;
    }
    return self;
}
- (instancetype) initWithName:(NSString*)name age:(int) age {
    if ( self = [super init] ) {
        _name = name;
        _age = age;
    }
}

子类的init方法应指定调用父类的哪个init方法

如Person子类Student类:

- (instancetype) initWithName:(NSString *)name age:(int) age score:(int) score  {
    if ( self = [super initWithName:name age:age] ) {
        //也可以用super的init方法及set方法,但不推荐
        _score = score;
    }
    return self;
}

有时我们需要创建一个现有对象的副本,则应编写一个拷贝构造方法,参数为对象指针

- (instancetype) initWithPerson:(Person*) p
{
    if  ( self = [super init] ) {
        _age = p.age;
        _name = p.name;
    }
    return self;
}

一个对象销毁时,会调用一个dealloc方法

     - (void)dealloc

     该方法在最后应调用父类的dealloc方法

     dealloc方法不能直接调用

     需要注意的是,在引入ARC机制后,重写这个方法时不能调用父类被重写的dealloc方法



  • 类对象

我们定义的类也是一种对象 ,是Class类的对象

Class创建Person类对象,再通过Person类对象方法来创建对象。

     这里:类对象 == 类

之前说过,每个对象都一个isa指针,isa指针指向就是类对象

     Objective-C(6)对象的构造

方法的调用过程:

      实际上就是通过基类部分的isa属性,找到成员函数列表,再将消息传递的参数拿过来和函数列表中的参数对比。 在自己的函数列表中找不到就到父类的函数列表中去找,直到找到为止。


  • 类方法

通过对象调用的方法,称为对象方法,如init description等。

通过类对象调用的方法,称为类方法,如alloc new等。

+ (instancetype)alloc
+ (instancetype)new

     对象方法在声明和定义时,以-开头

     类方法在声明和定义时,以+开头

在类方法中,self表示类对象,super表示父类对象

类方法在子类中也可以被重写 ,类方法和对象方法可以重名

访问类对象:

     任意对象都可以通过class方法,获得其类对象

- (Class)class

     也可以通过类的class类方法,获得其类对象     

+ (Class)class

如:(c1和c2是同一类对象)

Person *p1 = [Person new];
Person *p2 = [Person new];
Class c1 = [p1 class];
Class c2 = [p2 class];
Person *p3 = [c1 new];


类对象的加载

在程序运行开始时,会加载一次项目中所有的类,类加载完毕就会调用类的load方法。

     程序在第一次使用这个类时,会调用类的initialize方法。

     这两个方法是可以重写的,都是类对象方法

+ (void)load
+ (void)initialize

注意:

     使用第一次使用该类时,会先调用该类的父类的initialize方法

     当有分类时,类和分类的load方法都会被调用;第一次使用该类时,只会调用分类的initialize方法。


  • 类方法封装对象的创建

当实例化一个对象时,需要编写类似下面的代码:

Person *p = [[Person alloc] initWithAge:20];


这样的代码比较啰嗦,可以添加一个类方法来简化:

+ (instancetype) personWithAge:(int) age
{
     return [[Person alloc] initWithAge:age];
}


这样实例化对象的代码为:

Person *p = [Person personWithAge:20];