OC(构造函数,分类等知识总结)
文章來源:http://my.oschina.net/luoguankun/blog/219532
一、成員變量的作用域
· @public
· 在任何地方都能直接訪問對象的成員變量
· @private
· 只能在當前類的對象方法中訪問
· @protected(可以不寫,默認)
· 能在當前類和子類的對象方法中直接訪問
· @package
· 只要處在同一個框架中,就能直接訪問對象的成員變量
· @interface和@implementation中不能聲明同名的成員變量
· 在@implementation中聲明變量,默認是@private的
二、點語法
· 點語法的本質還是方法調用,不是調用成員變量
· 編譯器遇到點語法時,會把點語法轉成方法
?
|
1 2 3 |
p.age = 10; //[p setAge:10]; intage = p.age; //[p age]; |
三、構造方法
· 用來初始化對象的方法,對象方法,以減號開頭
· 為了讓對象創建出來,成員變量就會有一些固定的值
· 重寫構造方法的注意點:
· 先調用父類的構造方法([super init])
· 再進行子類內部成員變量的初始化
· + alloc 方法
· 分配存儲空間
· - init 方法
· 初始化
· 實際上是這么創建對象的
?
|
1 |
Person *p5 = [[Person alloc] init]; //先分配存儲空間,再進行初始化 |
· 重寫NSObject類的init方法(無參數)
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
- (id)init { //一定要調用回super得init方法:初始化父類中聲明的一些成員變量和其他屬性 if(self = [super init]) { //初始化成功 _age = 10; } returnself; } |
· 帶參數的構造方法
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
- (id)initWithName:(NSString *)name andAge:(int)age { if(self = [super init]) { _age = age; _name = name; } returnself; } |
四、分類
· 分類,在不改變原來模型的情況下,可以給某個類擴充一些方法
· 分類只能增加方法,不能增加成員變量
· 分類方法實現中可以訪問原來類中聲明的成員變量
· 分類的優先級最高,方法優先去分類中去找,再去原來類中去找,最后再去父類中找
· 分類可以重寫原來類中的方法,但是會覆蓋掉,會導致原來的方法失效,沒法再使用
· 方法調用的優先級:分類(最后參與編譯的分類優先) --> 原來類 --> 父類
· 分類的應用一般是擴展系統的類的方法,比如擴展NSString類的方法
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
+ (int)numberCountOfString:(NSString *)str { intcount = 0; for(unsigned longi = 0; i < [str length]; i++) { unichar ch = [str characterAtIndex:i]; if(ch >= '0'&& ch <='9') { count++; } } returncount; //return [str numberCount]; } //計算某個字符串中阿拉伯數字的個數(對象方法) - (int)numberCount { intcount = 0; for(unsigned i = 0 ; i < [self length]; i++) { unichar ch = [self characterAtIndex:i]; if(ch >= '0'&& ch <='9') { count++; } } returncount; //return [NSString numberCountOfString:self]; } |
五、類的本質
· 可以使用類創建對象,但是類本身也是一個對象,是個Class類型的對象,簡稱“類對象
· 先利用Class創建一個Person類對象,再利用Person類對象,創建Person類型的對象
· 重寫load()方法和initialize()方法
?
|
1 2 3 4 5 6 7 8 9 10 11 |
+ (void)load { NSLog(@"Student的load方法被調用"); } //在第一次被使用的時候就會被調用一次,監聽類第一次被使用的時候 + (void)initialize { NSLog(@"Student-initialize方法被調用"); } |
· load()方法:
· 當程序啟動時,就會加載項目中所有的類和分類,而且加載后會調用每個類和分類的load方法。只會調用一次
· 當第一次使用某個類時,就會調用當前類的+initialize方法
· 先加載父類,再加載子類(先調用父類的load方法,再調用子類的load方法)
· 先初始化父類,再初始化子類(先調用父類的initialize方法,再調用子類的initialize方法
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
//利用Person這個類創建了3個Person類型的對象 Person *p = [[Person alloc] init]; Person *p2 = [[Person alloc] init]; Person *p3 = [[Person alloc] init]; //先利用Class創建一個Person類對象 //再利用Person類對象,創建Person類型的對象 //獲取內存中的類對象 Class c = [p class]; Class c2 = [p class]; //獲取內存中的類對象 Class c3 = [Person class]; NSLog(@"c=%p,c2=%p,c3=%p",c,c2,c3); //c的地址等于c2,也等于c3 //程序先加載父類,再加載子類,而且類只被加載一次 //只要加載了類,就會調用load類方法 //initialize類方法是在類第一次被初始化時,被調用,如果在使用子類的時候,父類也會被調用該方法 //分類也會被加載,如果原始類和分類都重寫了initialize方法,那么分類的initialize方法優先被調用,原始類不調用 GoodStudent *stu = [[GoodStudent alloc] init]; |
六、自動生成getter和setter方法
· @property自動生成某個成員變量的聲明
· @synthesize自動生成getter和setter的實現,并且會訪問指定的成員變量
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
//自動生成某個成員變量的聲明 //編譯器特性:編譯器當遇到@property時,自動轉換成setter和getter聲明方法 // - (void)setAge:(int)age; // - (int)age; @propertyintage; //生成_age成員變量 @propertydoubleheight; //生成_height成員變量 @propertydoubleweight; //生成_weight成員變量 @property NSString *name; //生成_name成員變量 //@synthesize自動生成getter和setter的實現,并且會訪問指定的成員變量 @synthesize age = _age; @synthesize height = _height; //用逗號分隔 @synthesize weight = _weight,name = _name; |
· @synthesize可以不寫,只寫@property就可以完成成員變量getter和setter方法的聲明和實現
七、description方法
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
#import <Foundation/Foundation.h> #import "Person.h" intmain() { //輸出行號 NSLog(@"%d",__LINE__); //NSLog輸出C語言字符串的時候,不能有中文 NSLog(@"%s",__FILE__); //輸出源文件路徑名稱 printf("%s\n",__FILE__); //輸出當前函數名 NSLog(@"%s",__func__); return0; } voidtest() { Person *p = [[Person alloc] init]; p.age = 20; p.name = @"Jack"; //1.首先會調用對象的-description方法,返回字符串 //2.拿到-description方法的返回值,并顯示到屏幕上 //description方法默認返回“類名+內存地址” <Person 0x0232010> //所以需要重寫description方法 //相當于java的Object的toString()方法 NSLog(@"%@",p.description); Person *p2 = [[Person alloc] init]; p2.age = 22; p2.name = @"Ted"; NSLog(@"%@",p2.description); } voidtest2() { Class c = [Person class]; //1.首先會調用類的+description方法 //2.拿到+description方法的返回值(NSString *)顯示到屏幕上 NSLog(@"%@",c); } //重寫description方法 - (NSString *)description { //死循環 //NSLog(@"%@",self); return[NSString stringWithFormat:@"age=%d,name=%@",_age,_name]; } + (NSString *)description { return@"sss"; } |
八、id類型
· id是一種類型
· id是萬能指針,能操作任何OC對象,id內部已經包含*,所以不用再加*
· 示例:
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
intmain() { //id是一種類型 //id是萬能指針,能操作任何OC對象,id內部已經包含*,所以不用再加* //id d; //Person *p = [Person new]; //id == NSObject* //NSObject *o = [Person new]; //只適用OC對象 id person = [Person new]; [person setAge:10]; [person setObj:@"luoguankun"]; NSLog(@"age=%d",[person age]); test(person); return0; } |
九、SEL
· SEL其實是對方法的一種包裝,將方法包裝成一個SEL類型的數據,去找對應的方法地址,找到方法地址就可以調用方法
· 其實消息就是SEL
?
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
intmain() { //[Person test]; Person *p = [[Person alloc] init]; //1.把test2包裝成SEL類型的數據 //2.根據SEL數據找到對應的方法地址 //3.根據方法地址調用對應的方法 //[p test2]; //通過SEL簡介調用test方法 [p performSelector:@selector(test2)]; //上面的調用相當于下面這兩步 //SEL s = @selector(test2); //[p performSelector:s]; //通過SEL帶參數的形式調用test3方法,不要忘了帶上冒號 [p performSelector:@selector(test3:andluo:) withObject:@"luo"withObject:@"feng"]; return0; } //字符串轉換成SEL NSString *name = @"test2"; SEL s = NSSelectorFromString(name); //SEL轉換成字符串 - (void)test2 { //死循環 //[self performSelector:_cmd]; //_cmd是SEL類型,代表當前方法 //通過NSString的fromSelector方法把SEL轉換為字符串 NSString *str = NSStringFromSelector(_cmd); //打印_cmd NSLog(@"%@",str); //打印test2 } |
總結
以上是生活随笔為你收集整理的OC(构造函数,分类等知识总结)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Cloud云服务架构 -
- 下一篇: 【js】什么是函数节流与函数去抖