在第5講中已經介紹瞭如何定義類和建立並初始化對象,好比有Student這個類html
#import <Foundation/Foundation.h> @interface Student : NSObject { int _age; } - (void)setAge:(int)age; - (int)age; @end
#import "Student.h" @implementation Student - (void)setAge:(int)age { _age = age; } - (int)age { return _age; } @end
#import "Student.h" int main(int argc, const char * argv[]) { @autoreleasepool { Student *stu = [[Student alloc] init]; stu.age = 10; [stu release]; } return 0; }
* 在第7行調用Student的alloc方法分配內存,而後再調用init方法初始化對象ios
* 像init這樣用來初始化對象的方法,咱們能夠稱爲"構造方法"函數
默認的構造方法,也就是init方法,它是不接收任何參數的。所以,在實際開發中,爲了方便,會常常自定義構造方法。spa
接下來,自定義一個構造方法,能夠傳入一個age參數來初始化Student對象code
- (id)initWithAge:(int)age;
* 構造方法的方法名通常都會以init開頭,返回值跟init方法同樣爲id類型,id能夠表明任何OC對象orm
* 這個構造方法接收一個int類型的age參數,目的是在初始化Student對象時,順便設置成員變量_age的值htm
- (id)initWithAge:(int)age { self = [super init]; if (self != nil) { _age = age; } return self; }
* 跟Java同樣,構造方法內部首先要調用父類的構造方法,在第2行調用了父類的init方法,它會返回初始化好的Student對象,這裏把返回值賦值給了self,self表明Student對象自己對象
* 第3~5行的意思是:若是self不爲nil,也就是初始化成功,就給成員變量_age進行賦值blog
* 最後返回初始化事後的self,整個構造方法就結束了ip
因爲C語言和OC的語法特性,咱們能夠對構造方法進行簡化,先簡化第3行
- (id)initWithAge:(int)age { self = [super init]; if (self) { _age = age; } return self; }
* 第3行的 if(self) 跟 if(self!=nil) 是等價的
* 還能夠將第二、3行合併,繼續簡化
- (id)initWithAge:(int)age { if ( self = [super init] ) { _age = age; } return self; }
* 第2行的整體意思是:先調用父類的構造方法init,而後將返回值賦值給self,接着判斷self是否爲nil
* 之後的構造方法都這樣寫了
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
衆所周知,咱們能夠用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
其實,除了能夠輸出基本數據類型,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方法
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
千萬不要在description方法中同時使用%@和self,下面的寫法是錯誤的:
1 - (NSString *)description { 2 return [NSString stringWithFormat:@"%@", self]; 3 }
第2行同時使用了%@和self,表明要調用self的description方法,所以最終會致使程序陷入死循環,循環調用description方法
注:本文轉自M了個J博客。