接著上文/kf/201202/119761.html來說,上面我們是定義了一個接口的定義,下面我們來實現它,object c中的類文件使用擴展名m.
[plain]
Fraction.m
#import "Fraction.h"
@implementation Fraction
-(void) setNumerator: (int) n{
numerator=n;
-(void) setDenominator: (int) d{
denominator=d;
}
-(void) setNumerator: (int) n andDenominator: (int) d{
numerator=n;
denominator=d;
}
-(int) numerator{
return numerator;
}
-(int) denominator{
return denominator;
}
-(void) print{
printf("%d/%d\n",numerator,denominator);
}
-(void) m{
printf("-m:The class variable t is %d\n",++t);
}
+(void) t{
printf("+t:The class variable t is %d\n",++t);
}
@end
因為我們將Fraction.m 與Fraction.h 放在一個文件夾下面,所以#import 使用了” ”,這個類的
任務就是實現接口中的方法,因此與接口的結構不同的地方就是,你不能在這裡定義變量,
@interface 換成了@implementation,其余就沒有什麼特別的了。你不必在這裡實現@interface
中的全部方法,這不會導致錯誤。這裡有個-(void) m 方法比較特別,我們並沒有在@interface
中聲明,那麼這個方法可以調用嗎?因為Object-C 是動態語言,即便是@interface 中沒有定
義的方法,依然可以被調用。
另外,你需要注意的是setter 方法與接口中不同的是參數名縮寫成了n、d,這是因為在方
法中,本地變量(參數、方法中定義的變量)在名稱沖突的情況下,會隱藏成員變量,因此
導致numerator=numerator 變成了無意義的操作。當然你可以使用後面提到的self 關鍵
字,寫成 self->numerator=numerator,也就是JAVA 中的常用的this.x=x 的寫法。
下面我們編寫調用代碼,因為Object-C 基於C 語言,所以程序的入口依然是main 函數。這
裡注意#import 的是h,不是m。代碼如下:
main.m
[html]
#import "Fraction.h"
int main(int argc,const char *argv[]){
Fraction *frac=[[Fraction alloc] init];
[frac setNumerator: 3 andDenominator: 5];
[frac print];
printf("The denominator of Fraction is %d\n",frac->denominator);
[Fraction t];//調用類方法
[frac m];
[frac release];
return 0;
}
(1.) 第一行我們創建了Fraction 的實例(對象),Object-C 中實例只能使用指針作為變量,而
不能使用值,所以你看到了*frac,而不是frac,這與JAVA 是一致的,JAVA 中的指向實
例的變量(JAVA 中叫做引用)也是指針,只不過JAVA 中沒有指針的概念,所以你沒有
看到*。至於等號右側的創建實例的代碼,你可以在下面看到,這裡先不用理會。
(2.) 第二行代碼調用同時設置兩個變量的方法,我們看到Object-C 的調用方法的語法格式為
[類或者實例的指針 方法名: 參數1 標簽1: 參數2… …]。這種調用格式被稱為中綴
語法,初次看起來有點兒怪,但實際這樣更加有效。舉個例子,你接手了一個離職的人
程序,其中的JAVA 程序調用了一個有五個甚至更多的參數的方法,但是你手裡沒有這
個方法的API,那麼你很難猜得出來這五個參數到底都干什麼用的,但是Object-C 調用
的時候,每個參數前面都必須有方法的標簽名,這樣你便能很容易的從標簽名看出這個
參數是什麼意思。
(3.) 第四行在C 的printf()函數中使用了對象->成員變量的語法訪問實例的變量,但一般我
們不推薦這麼做,而是使用getter 方法。這裡你不能訪問numerator 變量,因為它是
@protected 的,只能本類、子類直接訪問。
(4.) 第五行我們調用了類方法t,你也可以換成這樣的寫法:
[[Fraction class] t];
或者
Class clazz=[Fraction class];
[clazz t];
class 方法是一個類方法,來自於NSObject,相當於JAVA 中的getClass()方法,也就是獲
取這個類的Class 對象,clazz 前面沒有*。另外這種嵌套調用的方式,你也要習慣,這就
和JAVA 中的A.b().c()沒有什麼區別。
(5.) 第六行我們調用了m 方法,這個方法你會發現並沒有在@interface 中聲明,這裡依然調
用了,只是在編譯的時候收到一個警告。這就是前面所有的Object-C 是動態語言的原因。
但是一般情況下,你都會給別人提供h 文件,所以你在m 文件中寫的h 文件中沒有的
方法,別人也是不會知道的,這個方法相當於變相的私有化了。
(6.) 第七行我們釋放了frac 實例在第一行alloc 所申請的內存空間,Object-C 的內存管理後面
會看到。另外,你會發現Fraction.h 中沒有定義alloc、init、release 方法,但是我們上面
調用了,很顯然,這些方法來自於父類NSObject。