天天看點

【Objective-C】06-點文法

前言

在Java中,我們可以通過"對象名.成員變量名"來通路對象的公共成員變量,這個就稱為"點文法"。比如:

1.在Student類的第2行定義了一個公共的成員變量age

1 public class Student {
2     public int age;
3 }      

2.然後在第5行通過點文法直接給stu的成員變量age指派

【Objective-C】06-點文法
1 public class Test {
2 
3     public static void main(String[] args) {
4         Student stu = new Student();
5         stu.age = 10;
6     }
7 
8 }      
【Objective-C】06-點文法

當然,正規的做法是讓成員變量私有化,讓外界使用公共的get方法和set方法通路成員變量。

3.很多進階語言中都有這種點文法,為了讓其他行業的程式員快速上手OC,OC中也引入了點文法,隻不過它的含義跟Java不太一樣

一、傳統的get方法和set方法

在正式學習OC的點文法之前,先來看一下傳統的get方法和set方法。定義一個Student類,擁有一個成員變量age和對應的get\set方法。

1.Student.h

【Objective-C】06-點文法
1 #import <Foundation/Foundation.h>
 2 
 3 @interface Student : NSObject {
 4     int age;
 5 }
 6 
 7 - (void)setAge:(int)newAge;
 8 - (int)age;
 9 
10 @end      
【Objective-C】06-點文法

1> 在第4行定義了一個成員變量age,是@protected權限的,是以外界不能直接通路它

2> 在第7、8行分别聲明了age變量的set方法和get方法

2.Student.m

【Objective-C】06-點文法
1 #import "Student.h"
 2 
 3 @implementation Student
 4 
 5 - (void)setAge:(int)newAge {
 6     age = newAge;
 7 }
 8 
 9 - (int)age {
10     return age;
11 }
12 
13 @end      
【Objective-C】06-點文法

1> 在第5行實作了set方法

2> 在第9行實作了get方法

3.main.m

把定義好的Student類放到main函數中使用

【Objective-C】06-點文法
1 #import <Foundation/Foundation.h>
 2 #import "Student.h"
 3 
 4 int main(int argc, const char * argv[])
 5 {
 6     @autoreleasepool {
 7         Student *stu = [[Student alloc] init];
 8         
 9         // 設定age的值
10         [stu setAge:10];
11         
12         // 取出age的值
13         int age = [stu age];
14         
15         NSLog(@"age is %i", age);
16         
17         [stu release];
18     }
19     return 0;
20 }      
【Objective-C】06-點文法

1> 在2行包含Student的頭檔案

2> 在第7行建立Student對象,在第17行釋放Student對象

3> 在第10行調用set方法設定age的值

4> 在第13行調用get方法擷取age的值

5> 在第15行輸出age的值,輸出結果如下:

2013-04-08 00:26:19.002 點文法[6164:303] age is 10      

這就是OC傳統的get方法和set方法的簡單使用,對初學者來說,這個文法比較奇怪,因為它的方法調用是用方括号[ ]完成的。是以,OC最終引入了點文法。

二、使用點文法代替傳統的get方法和set方法

上面示範了OC傳統get\set方法的簡單用法,接下來使用點文法來代替。

前面main.m中main函數的代碼可以改為:

【Objective-C】06-點文法
1 int main(int argc, const char * argv[])
 2 {
 3     @autoreleasepool {
 4         Student *stu = [[Student alloc] init];
 5         
 6         // 設定age的值
 7         stu.age = 10; // 等價于[stu setAge:10];
 8         
 9         // 取出age的值
10         int age = stu.age; // 等價于int age = [stu age];
11         
12         NSLog(@"age is %i", age);
13         
14         [stu release];
15     }
16     return 0;
17 }      
【Objective-C】06-點文法

1.注意第7行代碼,把原來的[stu setAge:10]替換成了stu.age = 10。聽清楚了,這兩種寫法是完全等價的。即這裡的stu.age并不是代表直接通路stu對象的成員變量age,而是編譯器遇到stu.age = 10的時候會自動将代碼展開成[stu setAge:10]

【Objective-C】06-點文法

再說,如果是直接通路成員變量的話,OC中應該是這樣的文法:stu->age,而不是stu.age。

2.注意第10行代碼,把原來的int age = [stu age]替換成了int age = stu.age。這兩種寫法又是完全等價的,stu.age并不是直接通路stu對象的成員變量age,而是編譯器遇到int age = stu.age的時候會自動将代碼展開成int age = [stu age]

【Objective-C】06-點文法

3.是以,OC中點文法的含義跟Java是完全不一樣的,OC點文法的本質是方法調用,不是直接通路成員變量。至于這個點文法代表的是get方法還是set方法,那就取決于你是取值還是設值,取值就是get方法(如第10行代碼),設值就是set方法(如第7行代碼)。

4.如果你想驗證點文法是不是方法調用的話,有很多方法。

比如你可以在Student.m的set方法和get方法内部用NSLog加一些列印資訊,如果程式運作後有輸出列印資訊,說明的确是調用了get方法或者set方法

【Objective-C】06-點文法
1 #import "Student.h"
 2 
 3 @implementation Student
 4 
 5 - (void)setAge:(int)newAge {
 6     NSLog(@"調用了setAge方法");
 7     age = newAge;
 8 }
 9 
10 - (int)age {
11     NSLog(@"調用了age方法");
12     return age;
13 }
14 
15 @end      
【Objective-C】06-點文法

三、點文法和self的陷阱

1.在Java中,this關鍵字代表着方法調用者,也就是說,誰調用了這個方法,this就代表誰。是以一般會這樣寫set方法:

1 public void setAge(int newAge) {
2     this.age = newAge;
3 }      

第2行表示将newAge參數的值,指派給方法調用者的成員變量age

2.OC中有個self關鍵字,作用跟this關鍵字類似。我這麼說完,可能有人就會想這樣寫OC的set方法了:

1 - (void)setAge:(int)newAge {
2     self.age = newAge;
3 }      

第2行中的self代表着目前調用setAge:方法的對象。但是第2行代碼是絕對錯誤的,會造成死循環。因為我在前面已經說過了,OC點文法的本質是方法調用,是以上面的代碼相當于:

1 - (void)setAge:(int)newAge {
2     [self setAge:newAge];
3 }      

很明顯,會造成循環調用setAge:方法,程式就這樣崩潰了

四、一點小建議

【Objective-C】06-點文法
1 #import <Foundation/Foundation.h>
 2 
 3 @interface Student : NSObject {
 4     int _age;
 5 }
 6 
 7 - (void)setAge:(int)newAge;
 8 - (int)age;
 9 
10 @end      
【Objective-C】06-點文法
【Objective-C】06-點文法
1 #import "Student.h"
 2 
 3 @implementation Student
 4 
 5 - (void)setAge:(int)newAge {
 6     _age = newAge;
 7 }
 8 
 9 - (int)age {
10     return _age;
11 }
12 
13 @end      

繼續閱讀