【Objective-C】07-自定义构造方法和description方法

 
// 构造方法:用来初始化对象的方法,是个对象方法,”-"开头
// 重写构造方法的目的:为了让对象创建出来,成员变量就会有一些固定的值
/*
 重写构造方法的注意点
1.先调用父类的构造方法([super init])
2.再进行子类内部成员变量的初始化
 */

// 重写-init方法
//- (id)init
//{
//    // 1.一定要调用回super的init方法:初始化父类中声明的一些成员变量和其他属性
//    self = [super init]; // 当前对象 self
//    
//    
//    // 2.如果对象初始化成功,才有必要进行接下来的初始化
//    if (self != nil)
//    { // 初始化成功
//        _age = 10;
//    }
//    
//    // 3.返回一个已经初始化完毕的对象
//    return self;
//}


    // Person *p = [Person new];
    /*
     完整地创建一个可用的对象
     1.分配存储空间  +alloc
     2.初始化 -init
     */
    
    // 1.调用+alloc分配存储空间
    // Person *p1 = [Person alloc];
    // 2.调用-init进行初始化
    // Person *p2 = [p1 init];
    
//    // 调用-init进行初始化
//    Person *p3 = [Person new];
//    
//    
//    // 每个Person对象创建出来,他的_age都是10


/*
 自定义构造方法的规范
 1.一定是对象方法,一定以 - 开头
 2.返回值一般是id类型
 3.方法名一般以initWith开头
*/

- (id)initWithName:(NSString *)name;


// 父类的属性交给父类方法去处理,子类方法处理子类自己的属性
- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no
{
    // 将name、age传递到父类方法中进行初始化
    if ( self = [super initWithName:name andAge:age])
    {
        _no = no;
    }
    
    return self
;
}

description决定了类的输出结果:
Class c = [Person class];
    
    // 1.会调用类的+description方法
    // 2.拿到+description方法的返回值(NSString *)显示到屏幕上
    NSLog(@"%@"
, c);
 
默认情况下,利用NSLog和%@输出对象时,结果是<类名,内存地址>
 
Person *p = [[Person alloc] init];
    
    // 指针变量的地址
    NSLog(@"%p", &p);
    // 对象的地址
    NSLog(@"%p", p);
    // <类名:对象地址>
    NSLog(@"%@", p);
 
 
 决定了实例对象的输出结果
- (NSString *)description
{
    // 下面代码会引发死循环,调用自身。
    // NSLog(@"%@", self);
    return [NSString stringWithFormat:@"age=%d, name=%@", _age, _name];
    //return @"3424324";

}


知识回顾

第5讲中已经介绍了如何定义类和创建并初始化对象,比如有Student这个类

1.Student.h

1 #import <Foundation/Foundation.h>
2
3 @interface Student : NSObject {
4 int _age;
5 }
6 - (void)setAge:(int)age;
7 - (int)age;
8 @end

2.Student.m

 1 #import "Student.h"
2
3 @implementation Student
4 - (void)setAge:(int)age {
5 _age = age;
6 }
7 - (int)age {
8 return _age;
9 }
10 @end

3.在main函数中创建一个Student对象

 1 #import "Student.h"
2
3 int main(int argc, const char * argv[])
4 {
5
6 @autoreleasepool {
7 Student *stu = [[Student alloc] init];
8
9 stu.age = 10;
10
11 [stu release];
12 }
13 return 0;
14 }

* 在第7行调用Student的alloc方法分配内存,然后再调用init方法初始化对象

* 像init这样用来初始化对象的方法,我们可以称为"构造方法"

一、自定义构造方法

默认的构造方法,也就是init方法,它是不接收任何参数的。因此,在实际开发中,为了方便,会经常自定义构造方法。

接下来,自定义一个构造方法,可以传入一个age参数来初始化Student对象

1.在Student.h中添加方法声明

- (id)initWithAge:(int)age;

* 构造方法的方法名一般都会以init开头,返回值跟init方法一样为id类型,id可以代表任何OC对象

* 这个构造方法接收一个int类型的age参数,目的是在初始化Student对象时,顺便设置成员变量_age的值

2.在Student.m中实现构造方法

1 - (id)initWithAge:(int)age {
2 self = [super init];
3 if (self != nil) {
4 _age = age;
5 }
6 return self;
7 }

* 构造方法内部首先要调用父类的构造方法,在第2行调用了父类的init方法,它会返回初始化好的Student对象,这里把返回值赋值给了self,self代表Student对象本身

* 第3~5行的意思是:如果self不为nil,也就是初始化成功,就给成员变量_age进行赋值

* 最后返回初始化过后的self,整个构造方法就结束了

3.简化构造方法

由于C语言和OC的语法特性,我们可以对构造方法进行简化,先简化第3行

1 - (id)initWithAge:(int)age {
2 self = [super init];
3 if (self) {
4 _age = age;
5 }
6 return self;
7 }

* 第3行的 if(self) 跟 if(self!=nil) 是等价的

* 还可以将第2、3行合并,继续简化

1 - (id)initWithAge:(int)age {
2 if ( self = [super init] ) {
3 _age = age;
4 }
5 return self;
6 }

* 第2行的总体意思是:先调用父类的构造方法init,然后将返回值赋值给self,接着判断self是否为nil

* 以后的构造方法都这样写了

4.调用构造方法

1 Student *stu = [[Student alloc] initWithAge:10];
2
3 NSLog(@"age is %i", stu.age);
4
5 [stu release];

* 在第1行调用了构造方法initWithAge:,并传入10作为参数,因此Student对象的成员变量_age会变为10

* 在第3行打印Student的成员变量_age,打印结果:

2013-04-19 21:36:47.880 构造方法[448:303] age is 10

二、description方法

1.NSLog回顾

众所周知,我们可以用NSLog函数来输出字符串和一些基本数据类

1 int age = 11;
2 NSLog(@"age is %i", age);

* 第2行的%i代表会输出一个整型数据,右边的变量age会代替%i的位置进行输出

* 输出结果:

2013-04-19 21:43:47.674 构造方法[483:303] age is 11

2.NSLog输出OC对象

其实,除了可以输出基本数据类型,NSLog函数还可以输出任何OC对象

1 Student *stu = [[Student alloc] initWithAge:10];
2
3 NSLog(@"%@", stu);
4
5 [stu release];

* 在第3行用NSLog函数输出stu对象,注意左边的格式符%@,以后想输出OC对象,就得用%@这个格式符

* NSLog函数一旦发现用%@输出某个OC对象时,就会调用这个对象的description方法(这个方法返回值是NSString类型,是OC中的字符串类型),并且将description方法返回的字符串代替%@的位置进行输出

* description方法的默认实现是返回这样的格式:<类名: 对象的内存地址>,因此上面代码的输出结果为:

2013-04-19 21:46:49.896 构造方法[492:303] <Student: 0x100109910>

Student是类名,0x100109910是对象的内存地址

* 注意了,%@只能用于输出OC对象,不能输出结构体等其他类型

3.重写description方法

description方法的默认实现是返回类名和对象的内存地址,这样的话,使用NSLog输出OC对象,意义就不是很大,因为我们并不关心对象的内存地址,比较关心的是对象内部的一些成变量的值。因此,会经常重写description方法,覆盖description方法的默认实现

比如,重写Student的description方法,返回成员变量_age的值

1 - (NSString *)description {
2 return [NSString stringWithFormat:@"age=%i", _age];
3 }

* 在第2行调用了NSString这个类的静态方法stringWithFormat初始化一个字符串对象,并返回这个字符串

* 如果你会使用NSLog的话,那就应该能理解第2行的方法参数是什么意思了

* 假如_age是10,那么description方法返回的字符串就是@"age=10"

* 可能有人会觉得奇怪,之前创建的Student对象是需要释放的,为什么这里创建的字符串对象不用释放?要想彻底明白这个问题,需要先了解OC的内存管理,这里我们暂不做详细讨论,后面会有章节详细讨论内存管理。你可以先记住一个规则:一般情况下,静态方法返回的对象,都不用手动释放。

* 重写完description方法后,再次执行下面的代码

1 Student *stu = [[Student alloc] initWithAge:10];
2
3 NSLog(@"%@", stu);
4
5 [stu release];

输出结果为:

2013-04-19 22:09:56.625 构造方法[531:303] age=10

4.description方法的陷阱

千万不要在description方法中同时使用%@和self,下面的写法是错误的:

1 - (NSString *)description {
2 return [NSString stringWithFormat:@"%@", self];
3 }

第2行同时使用了%@和self,代表要调用self的description方法,因此最终会导致程序陷入死循环,循环调用description方法

SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址。找到方法地址就可以调用方法。

最新文章

  1. iOS开发资源(持续更新)
  2. shell学习--grep1
  3. Linux下,telnet命令如何退出
  4. wordpress安装步骤
  5. Java随学随记
  6. SQLServer 索引以及视图
  7. 【转】Android SDK Manager 更新方法
  8. bzoj1103
  9. 数据结构——POJ 1686 Lazy Math Instructor 栈的应用
  10. 会话控制session,cookie(0521)
  11. Random随机数
  12. 提升iOS审核通过率之“IPv6兼容测试”
  13. Syntax error on tokens, delete these tokens.问题解决
  14. css中的几个小tip(一)
  15. 从JDK源码角度看并发锁的优化
  16. 百度搜索(jsonp)
  17. mongo分片集群部署
  18. Ultimate Guide to WhatsApp for Business 2019
  19. Linux 常用性能分析命令
  20. ubuntu安装Qt

热门文章

  1. [Linked List]Remove Duplicates from Sorted List
  2. typedef用法总结。
  3. Android 弹出窗体
  4. Android 混淆文件project.properties和proguard-project.txt
  5. linux c语言连接mysql
  6. 【转】vs2010下创建webservice
  7. ORM和Core
  8. Oracle EBS-SQL (WIP-7):检查当月任务发放记录.sql
  9. Flex中如何通过showAllDataTips属性使鼠标移动到图表时显示所有的数据Tips的例子
  10. 复旦大学EWP菁英女性课程(复旦卓越女性课程改版后第一期) _复旦大学、女性课程、高级研修班、心理学、EWP_培训通课程