zoukankan      html  css  js  c++  java
  • OC语言--自定义构造方法和description方法

    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 }

    * 跟Java一样,构造方法内部首先要调用父类的构造方法,在第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对象,不能输出结构体等其他类型

    * 有Java开发经验的人应该能感受到OC中的description方法就是Java中的toString方法

    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:全称Selector 表示方法的存储位置。

    方法在内存中是怎么存储的?

     

    Person *p=[[Person alloc] init];

    [p test];

    寻找方法的过程:

    (1)首先把test这个方法名包装成sel类型的数据;

    (2)根据SEL数据找到对应的方法地址;

    (3)根据方法地址调用相应的方法。

    (4)注意:在这个操作过程中有缓存,第一次找的时候是一个一个的找,非常耗性能,之后再用到的时候就直接使用。

    关于_cmd:每个方法的内部都有一个-cmd,代表着当前方法。

     

    注意:SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去寻找对应的方法地址,找到方法地址后就可以调用方法。这些都是运行时特性,发消息就是发送SEL,然后根据SEL找到地址,调用方法。

  • 相关阅读:
    js中的原生Ajax和JQuery中的Ajax
    this的用法
    static的特性
    时政20180807
    java compiler没有1.8怎么办
    Description Resource Path Location Type Java compiler level does not match the version of the installed Java project facet Unknown Faceted Project Problem (Java Version Mismatch)
    分词器
    [数算]有一个工程甲、乙、丙单独做,分别要48天、72天、96天完成
    一点感想
    解析Excel文件 Apache POI框架使用
  • 原文地址:https://www.cnblogs.com/jiqiaochun/p/4716018.html
Copyright © 2011-2022 走看看