OC-@property、self及類的本質,oc-@propertyself
讓代碼書寫更加簡便--1-- 設定器和訪問器1.1 setter1.2 getter--2-- 類的本質2.1 類類型的對象2.2 類的本質2.3 如何擷取類對象2.4 類對象的使用2.5 類對象的儲存--3-- SEL類型3.1 SEL--4-- @property關鍵字4.1 基本概念4.2 @property用法4.3 @property使用注意事項--5-- @synthesize關鍵字5.1 @synthesize用法5.2 @synthesize使用注意5.3 @synthesize指定執行個體變數賦值--6-- self關鍵字6.1 介紹6.2 在對象方法中使用self6.3 用在類方法中使用self
【寫在開頭】
『在物件導向的編程中,封裝是其一個重要的特性。封裝將一個可供外部使用的介面暴露出來,隱藏了複雜的代碼邏輯實現。
不可被外部任意儲存是物件導向設計的本質,降低了資料被無用的可能性。
外部就可以通過設定器setter和訪問器getter來對對象的屬性進行設定和訪問,而不是直接存取對象的屬性->
在開發過程中,考慮到安全性要求,一般不再成員變數名前面使用@public、@protected等關鍵字修飾,而是使用Set方法來為對象提供成員變數的值,在set方法的內部也可以對一些不合理的賦值進行篩選過濾。』
--1-- 設定器和訪問器1.1 setter
setter方法(設定器):在set方法的內部可以對一些不合理的資料過濾篩選。set方法作用:為提供一個設定成員變數值的方法。
命名規範:
1)方法名必須以set開頭
2)set後面跟上成員變數的名稱,首字母大寫
3)傳回值一定是void
4)一定要接受一個參數,而且參數類型需要和成員變數的類型一致
5)形參名不能和變數名一樣(成員變數名以_線開頭,蘋果官方推薦成員變數名前加_以示區分)
好處:
1)不讓資料暴露在外,保證了資料的安全性
2)對設定的資料進行過濾
{ //成員屬性 NSString *_name; int _age;}
setter
//setter- (void)setName:(NSString *)name;- (void)setAage:(int)age;
1.2 getter
作用:為調用者返回對象內部的成員變數
命名規範:
1)一定有傳回值,傳回值的類型和成員變數的類型一致
2)方法名和去掉底線的成員變數名一樣(此處與Java等語言不一樣)
3)不需要接收任何參數
//getter- (NSString *)name;- (int)age;
--2-- 類的本質2.1 類類型的對象
類的本質其實也是對象,只不過是class類型的對象,也叫做類對象
2.2 類對象
類對象
* 類對象在程式運行時一直存在
* 類對象是一種資料結構,儲存類的基本資料:類大小,類名,類的版本以及訊息與函數的映射表等
* 類對象所儲存的資訊是在程式編譯時間確定,在第一次使用該類的時候被載入到記憶體中
* 類對象代表類,class代表類對象,類方法屬於類對象
* 如果訊息的接收者是類名,則類名代表類對象
* 運行時,所有類的執行個體都由類對象產生,類對象會把執行個體的isa的值修改成自己的地址,每個執行個體的isa都指向該執行個體的類對象
* 從類對象裡可以知道父類的資訊、可以響應的方法等
* 類對象只能使用類方法,不能使用執行個體方法
2.3 如何擷取類對象
1)通過執行個體對象擷取
Person *person = [[Person alloc] init]; //建立對象 //通過執行個體對象擷取類對象Dog Class c1 = [person class]; //Class類型的是一個結構體指標 Class c2 = [person class]; NSLog(@"c1->%p", c1); //0x1000011d8 NSLog(@"c2->%p", c2); //0x1000011d8
2)通過類名擷取(類名其實就是類對象)
//通過類名擷取類對象 Class c3 = [Person class]; NSLog(@"c3->%p", c3); //0x1000011d8
發現通過類名和執行個體擷取對象,所獲得的對象是同一個
實際上,都是獲得了類對象Person class
2.4 類對象的使用
1)用類對象建立對象
兩個測試方法:
//對象方法- (void)test;//類方法+ (void)test;
使用
//用類對象來建立對象 Person *person2 = [[c1 alloc] init]; [person2 test]; //調用對象方法的test -test
2)用類對象來調用類方法
//用類對象來調用類方法 [c1 test]; //調用類方法 +test
2.5 類對象的儲存
isa指標
- 每一個對象都包含一個isa指標.這個指標指向當前對象所屬的類。
- [p eat];表示給p所指向的對象發送一條eat訊息,調用對象的eat方法,此時對象會順著內部的isa指標找到存 儲於類中的方法,執行。
- isa是對象中的隱藏指標,指向建立這個對象的類。
- 通過isa指標我們可以在啟動並執行時候知道當前對象是屬於那個Class(類)的。
--3-- SEL類型3.1 SEL
SEL:全稱selector,表示方法的儲存位置
方法調用的原理:其實每個類載入到記憶體中對象的方法都會封裝成一系列的SEL列表,SEL會儲存著這個方法的資訊(當然包括方法的記憶體位址),當要調用該方法的時候,對象會通過isa指標找到記憶體中對應的方法的記憶體位址然後再調用該方法,在找到該方法之後該類對象會把該SEL放入緩衝中,以便第二次尋找的時候提高效率
Person *p = [[Person alloc] init];
[p test];
尋找方法的過程
1)首先把test這個方法名封裝成SEL類型的資料
2)根據SEL資料找到對應的方法地址
3)根據方法地址調用相應的方法
4)注意:在這個操作過程中有緩衝,第一次找的時候是一個一個的找,非常耗效能,之後再用到的時候就直接使用了
--4-- @property關鍵字
4.1 基本概念
@property是編譯器的指令。(編譯器指令是由編譯器完成的)
好處是免去我們手工書寫成員屬性getter和setter方法繁瑣的代碼。
4.2 @property用法
格式:
@property 類型名 方法名
如:
@property int age;
相當於完成了age屬性的set和get方法的聲明和實現
- (void)setAge:(int)age;
- (void)age;
注意:
1、在Xcode4.4之前,用於幫我們實現get/set方法的聲明
2、在Xcode4.4之後,有增強功能,連實現也自動完成了
Person.h->
/* 省略了方法的聲明 相當於是替換了下面的這兩句聲明 - (void)setAge:(int)age; - (int)age; 同時,還自動產生了對應的成員屬性 _age,但是這個屬性是私人的,外部只能通過setter/getter訪問 */@property int age;
Person類中沒有自訂 _age屬性,但是@property自動產生了該屬性:
@implementation Person//對象方法- (void)test{ NSLog(@"-TEST"); self->_age = 3; //在這裡可以看到,@property產生了一個_age屬性}//類方法+ (void)test{ NSLog(@"+TEST");}@end
調用:
Person *person = [[Person alloc] init]; //建立對象 //此處 _age屬性由@property產生person.age = 3; //設定成員屬性NSLog(@"person.age->%d", person.age); //3
4.3 @property使用注意事項
在老式的代碼中
@property只能寫在@interface ...@end之間
@property用來自動產生成員變數get/set方法的聲明(Xcode4.4之前)
告訴@property要產生的get/set方法聲明的成員變數類型是聲明
告訴@property要產生的get/set方法是哪個屬性的,屬性名稱去掉底線
--5-- @synthesize關鍵字
5.1 @synthesize用法
@synthesize age;
寫在.m檔案中,表示對產生.h中變數age的get和set方法的實現
格式:
@synthesize 方法名
注意:
如果使用@synthesize則變數名要先在.h檔案中聲明
.h
@property int age;
.m
@synthesize age;
展開形式如下:
@synthesize age; //展開- (void)setAge:(int)age{ self->age = age; //注意這裡不是對Person原來的成員變數_age賦值,而是產生了一個變數age,然後對其進行賦值//(如果這裡寫self,那麼這個變數age也就相當於是個成員變數了) //所以使用@synthesize時,下面只列印了age和name的值,沒有對_age和_name進行操作 //NSLog(@"age = %d, name = %@", age, name); //NSLog(@"_age = %d, _name = %@", _age, _name); }
5.2 @synthesize使用注意
Xcode4.4之前@property和@synthesize搭配使用,用於簡化set和get方法的定義和實現
5.3 @synthesize指定執行個體變數賦值
聲明
@property int a;
實現
@sythesize a = _b; //表示用a的get和set方法,修改屬性b的值
相當於下面的代碼:
- (void) setA:(int)a{
_b = a;
}
- (int)a{
reurn _b;
}
@interface Person : NSObject@property NSString *name;//如果兩個執行個體變數的類型一致,如:age和weight,@property可以用逗號隔開變數,在一行上定義@property int age, weight; //測試方法- (void)test;@end@implementation Person//用age的getter和setter方法,修改屬性_age的值@synthesize age = _age, name = _name, weight = _weight;@end
--6-- self關鍵字6.1 介紹
OC語言中的self,就相當於C++、Java中的this指標。
學會使用self,首先要搞清楚屬性這一概念。
以及理解getter(訪問器)和setter(設定器)方法,它到底有什麼用?
設定器與訪問器,提供外界操作 類內部屬性的一個通道。
假如,沒有這個方法,外界怎麼操作類的內部屬性。
假如不提供這兩個方法,那麼這個屬性的值,就不能為外界所改變。
因為類的屬性,預設是@protect(受保護類型)。
self的應用情境
1)用在類方法中
2)用在對象方法中
3)訪問成員變數
4)self在OC的記憶體管理特殊使用
6.2 在對象方法中使用self
//學生學習對象方法- (void)study{ //此時self指代學生對象 NSLog(@"- self->%p", self); //0x1002001b0}
6.3 用在類方法中使用self
//學生資訊類方法+ (void)info{ //此時self指代學生類 NSLog(@"+ self->%p", self); //0x1000013d0}
查看:
@autoreleasepool { Student *stu = [[Student alloc] init]; //學生對象地址 NSLog(@"stu->%p", stu); //0x1002001b0 //學生類地址 NSLog(@"Student-%p", [Student class]); //0x1000013d0 //發送study和info訊息 [Student info]; //0x1000013d0 [stu study]; //0x1002001b0 }
輸出-->
綜上總結:
self要指代誰?具體是要看self寫在哪個方法中,
如果self寫在對象方法中,則指代的就是當前方法的對象([類 new])
如果self寫在類方法中,那麼它指代的就是當前的類對象(類 class)
注意這裡類對象和對象是兩個概念
【寫在結尾:】
『想起一首席慕容的詩:
一棵開花的樹如何讓你遇見我在我最美麗的時刻為這我已在佛前求了五百年求佛讓我們結一段塵緣佛於是把我化做一棵樹長在你必經的路旁陽光下謹慎地開滿了花朵朵都是我前世的盼望當你走近請你細聽那顫抖的葉是我等待的熱情而當你終於無視地走過在你身後落了一地的朋友啊那不是花瓣那是我凋零的心』