OC的构造方法init以及自定义构造方法

  • 之前我们利用类来创建对象用到了一个类方法new,可是new方法具体是怎么执行的呢?例如
1 Person *p = [Person new];

程序只要执行了这一行代码,内存中就会有一个Person类和Person对象,并且Person对象的所有实例变量都初始化为0,并且还有个isa指针指向Person类,那么这个对象实际上是通过两部产生的:第一步,调用Person类的alloc类方法分配一定的内存空间给Person对象,它的返回值就是对象本身,实际上也是这一段内存空间的首地址;第二步,调用对象init方法初始化对象的所有实例变量,并返回对象本身。由于OC本身的init方法很死板,他就是将所有实例变量初始化为0,但是用户往往是希望创建完了一个对象后,希望对象的某些实例变量有一个非0的初始值,所以重写init方法是很重要的。init方法的一般固定格式为:

 1 - (id)init{
 2     // 调用父类的init方法将返回值赋值给当前对象
 3     self = [super init]; // 固定写法
 4
 5     if( self != nil ){
 6         //需要自定义初始化的成员变量
 7     }
 8     // 对象初始化为我们想要的结果后,将对象本身返回
 9     return self;
10 }

当然上述代码也可以简化为:

1 - (id)init{
2
3     if( self = [super init] ){
4         //需要自定义初始化的成员变量
5     }
6     // 对象初始化为我们想要的结果后,将对象本身返回
7     return self;
8 }

代码实现:

 1 #import <Foundation/Foundation.h>
 2 /*******Person类******/
 3 @interface Person : NSObject
 4
 5 @property int age;
 6
 7 - (id)init;
 8
 9 @end
10
11 @implementation Person
12
13 - (id)init{
14     if ( self = [super init] ) {
15         _age = 1;
16     }
17
18     return self;
19 }
20
21 @end
22
23 /*******Student类*******/
24 @interface Student : Person
25
26 @property int score;
27
28 - (id)init;
29
30 @end
31
32 @implementation Student
33
34 - (id)init{
35     if ( self = [super init] ) {
36         _score = 60;
37     }
38
39     return self;
40 }
41
42 @end
43
44 int main() {
45     // 创建对象并调用调用重写的init对象方法
46     Person *p = [[Person alloc] init];
47     Student *stu = [[Student alloc] init];
48
49     // 测试init方法是否成功调用
50     NSLog(@"Person对象:年龄的初始值为%d", p.age);
51     NSLog(@"Student对象:年龄的初始值为%d,成绩的初始值为%d", p.age, stu.score);
52     return 0;
53 }
  • 但是这种重写init方法也有弊端,因为所有通过重写的init方法创建出来的对象的初始值都是一样的,即使他们都不为0,比如每个学生的姓名是不一样的,自然我们会想到自己写一个初始化方法来满足用户的要求,那么这种自定义的构造方法有什么规范呢?首先,方法名必须以init开头;其次因为是对象方法,所以是以减号‘-‘开头,并且它的返回值是oc对象,所以返回值为id类型;最后在方法里一定要调用父类对象方法[super init]。

假如有一个Person类,它有实例变量_age(int型)和_name(NSString *型),如果我要想每创建一个Person对象出来后它的_age和_name都不一样,我们可以采取自定义构造方法

 1 /*
 2 定义一个Person类,实例变量_age(int类型)和_name(NSString类型)
 3  要求:自定义一个构造方法,对象被创建出来后,_name和_age都有一个非0值
 4
 5  */
 6 #import <Foundation/Foundation.h>
 7
 8 @interface Person : NSObject
 9
10 @property int age;
11 @property NSString *name;
12
13 - (id)initWithName:(NSString *)name andAge:(int)age;
14
15 @end
16
17 @implementation Person
18
19 - (id)initWithName:(NSString *)name andAge:(int)age{
20     if ( self = [super init] ) {
21         _name = name;
22         _age = age;
23     }
24
25     return self;
26 }
27
28 @end
29
30 int main() {
31     // 创建两个对象并调用调用自定义构造对象方法
32     Person *p1 = [[Person alloc] initWithName:@"ZhangSan" andAge:15];
33
34     Person *p2= [[Person alloc] initWithName:@"LiSi" andAge:14];
35
36     // 测试自定义构造方法
37     NSLog(@"第1个Person对象:姓名为%@,年龄为%d", p1.name, p1.age);
38     NSLog(@"第2个Person对象:姓名为%@,年龄为%d", p2.name, p2.age);
39     return 0;
40 }

程序正常运行

如果我们要求在这个基础上再添加一个Person类的子类Student并且新添加一个实例变量_no(int类型),并且每创建一个Student类对象_no都有一个自己的初始值。代码如下:

 1 #import <Foundation/Foundation.h>
 2
 3 /**********Person类***********/
 4 @interface Person : NSObject
 5
 6 @property int age; // 年龄
 7 @property NSString *name; // 姓名
 8
 9 - (id)initWithName:(NSString *)name andAge:(int)age; // 自定义name和age的构造对象方法
10
11 @end
12
13 // Person类的实现
14 @implementation Person
15 // 自定义构造方法实现
16 - (id)initWithName:(NSString *)name andAge:(int)age{
17     if ( self = [super init] ) {
18         _name = name;
19         _age = age;
20     }
21
22     return self;
23 }
24
25 @end
26 /***********Student类***********/
27 @interface Student : Person
28
29 @property int no; // 学号
30 // 学生的自定义构造方法
31 - (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no;
32
33 @end
34
35 // Student类的实现
36 @implementation Student
37 // 学生的自定义构造方法的实现
38 - (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no{
39     if ( self = [super init]) {
40         _no = no;
41         self.name = name;
42         self.age = age;
43     }
44     return self;
45 }
46
47 @end
48
49 int main() {
50     // 创建两个对象并调用调用自定义构造对象方法
51     Student *stu1 = [[Student alloc] initWithName:@"ZhangSan" andAge:14 andNo:8];
52
53     Student *stu2= [[Student alloc] initWithName:@"LiSi" andAge:15 andNo:2];
54
55     // 测试自定义构造方法
56     NSLog(@"第1个Student对象:姓名为%@,年龄为%d,学号为%d", stu1.name, stu1.age, stu1.no);
57     NSLog(@"第2个Student对象:姓名为%@,年龄为%d,学号为%d", stu2.name, stu2.age, stu2.no);
58     return 0;
59 }

但是这个代码中的第41、42行是在子类的对象方法中对父类的实例变量修改值,这是不建议的。假如以后我们修改了父类的某一个属性名的话,那么子类的这种语句就会出错。一般是谁的属性那就用谁的方法去修改它,所以我们要把父类的这两个属性调用父类的方法去修改它,如何完成这个要求呢?我们只需要动一动学生的自定义构造方法的实现:

1 // 修改后的学生的自定义构造方法的实现
2 - (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no{
3     if ( self = [super initWithName:name andAge:no]) {
4         _no = no;
5         //self.name = name;
6         //self.age = age;
7     }
8     return self;
9 }

这种做法就保证了子类的属性交给子类去操作,父类的属性交给父类去操作,互不干扰

时间: 2024-08-14 01:07:40

OC的构造方法init以及自定义构造方法的相关文章

OC语法4——自定义构造方法,description方法

自定义构造方法: 我们已经知道创建对象分两步,1:在内存中开辟存储空间,并把地址存储在指针变量里,2:调用指针变量的初始化方法init初始化该对象. Student * stu = [Student alloc]; stu = [stu init]; 在这里,init方法是系统原始的初始化方法,但有时我们需要重写该初始化方法,使其在创建该对象的同时赋予它属性的值. 假如,我们现在要重写原始初始化方法,使其创建一个有年龄(age)的stu. 首先,在Student.h中声明自定义方法: - (id

OC中构造方法、自定义构造方法、id类型

一:id类型 1> id 是一种类型,万能指针,能够指向\操作任何的对象. typedef struct objc_object *id; 注意点:在使用id定义的时候,一定要注意(*)id类型默认已经包含了*所以不需要在加*; 局限性:调用一个不存在的方法,编译器会马上报错. 2>instancetype类型 (1)instancetype会让编译器检查实例化对象的准确类型 (2)instancetype只能用于返回类型,不能当做参数使用 3>.instancetype & i

OC中自定义构造方法

格式 -(instancetype)init(){ self=[super init] if(self){ } return self; } 自定义构造方法规范 1)一定是对象方法,以减号开头 2)返回值一般是id类型 3)方法名一般以initWith开头 带参数的构造方法 -(instatncetype) initWithName:(NSString *) name andAge:(int)age{ if(self=[super init]){ _age=age; _name=name; }

iOS开发核心语言Objetive C —— 编译器指令@[email&#160;protected]自定义构造方法及类工厂

本分享是面向有意向从事iOS开发的伙伴们,或者已经从事了iOS的开发者.如果您对iOS开发有极高的兴趣,可以与我一起探讨iOS开发,一起学习,共同进步.如果您是零基础,建议您先翻阅我之前分享的iOS开发分分钟搞定C语言系列,然后在开始Objective C语言的学习,如果您遇到问题也可以与我探讨,另外将无偿分享自己整理的大概400G iOS学习视频及学习资料,都是干货哦!可以新浪微博私信?关注极客James,期待与您的共同学习和探讨!!由于时间有限,每天在工作之余整理的学习分享,难免有不足之处,

继承中的自定义构造方法

1.继承中的自定义构造方法 不能在子类访问父类私有变量 @interface Person : NSObject @property int age; - (id)initWithAge:(int)age; @end @interface Student : Person @property NSString *name; - (id)initWithAge:(int)age andName:(NSString *)name; @end @implementation Student - (id

构造方法,自定义构造方法

// // main.m #import <Foundation/Foundation.h> #import "Iphone.h" int main(int argc, const char * argv[]) { /* Iphone * phone1 = [Iphone new]; phone1->_cpu = 1.5; phone1->_ram = 512; */ /*Iphone * phone = [Iphone alloc];//offcc phone

Objective-C - 自定义构造方法

自定义构造方法 @interface Person : NSObject @property NSString *name; @property int age; /* 自定义构造方法的规范 1.一定是对象方法,一定以 - 开头 2.返回值一般是id类型 3.方法名一般以initWith开头 */ - (id)initWithName:(NSString *)name; - (id)initWithAge:(int)age; // initWithName:andAge: - (id)initW

自定义构造方法

1.自定义构造方法 有时候仅仅靠重写构造方法(初始化方法),不能满足需求.比如一个班级中不可能所有学生的年龄都一样,这时候我们需要在创建某个学生的时候能够传入这个学生的年龄.这时候就需要来自定义构造函数(初始化函数) 自定义构造方法的规范 (1)一定是对象方法,以减号开头 (2)返回值一般是instancetype类型 (3)方法名必须以initWith开头 示例 @interface Person : NSObject @property int age; @property NSString

Java中,什么是构造方法?什么是构造方法重载?什么是复制构造方法?

什么是构造方法? 当新对象被创建的时候,构造方法就会被调用.每一个类都有构造方法,如果程序员没有给类提供构造方法,Java编译器会为这个类创建一个默认的构造方法. 什么是构造方法重载? 构造方法重载跟方法重载很相似,可以为一个类创建多个构造方法,每一个构造方法必须有它自己唯一的参数列表. 什么是复制构造方法? Java不支持构造方法的复制,复制构造方法是C++的内容. 原文地址:https://www.cnblogs.com/Freak-Lew/p/9191304.html