对象的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=[superinit]){_age=10;}returnself;}

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

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

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

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


自定义init方法

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

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

返回值一般是instancetype类型

方法名以initWith开头

如Person类中包含属性name和age

-(instancetype)initWithName:(NSString*)name{if(self=[superinit]){_name=name;}returnself;}-(instancetype)initWithName:(NSString*)nameage:(int)age{if(self=[superinit]){_name=name;_age=age;}}

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

如Person子类Student类:

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

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

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

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

- (void)dealloc

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

dealloc方法不能直接调用

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



类对象

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

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

这里:类对象 == 类

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

方法的调用过程:

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


类方法

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

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

+(instancetype)alloc+(instancetype)new

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

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

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

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

访问类对象:

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

-(Class)class

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

+(Class)class

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

Person*p1=[Personnew];Person*p2=[Personnew];Classc1=[p1class];Classc2=[p2class];Person*p3=[c1new];


类对象的加载

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

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

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

+(void)load+(void)initialize

注意:

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

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


类方法封装对象的创建

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

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


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

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


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

Person*p=[PersonpersonWithAge:20];