字體:小 中 大 | |
|
|
2011/02/17 09:16:44瀏覽966|回應1|推薦1 | |
這是Programming in Objective-C 2.0第三章的例子。首先用C的方式來寫,之後,會用Objective-C的語法來寫一樣結果的程式。
用C寫印出分式的程式 #import <Foundation/Foundation.h> (這裡的"<" ">"是用全型字符,不然在這裡印不出來。) int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; int numerator; int denominator; numerator=1; denominator=3; NSLog(@"分式是"); NSLog(@”%i/%i”,numerator,denominator); [pool drain]; return 0; } 輸出結果是 分式是 1/3 C的寫法就是宣告二個整數變數,然後把變數設定整數值,最後再用NSLog()把所要的結果印出來。 用Objective-C的寫法 在這個程式中,我們會定義一個Fraction class,這個Class是繼承(或遺傳自)NSObject class,這個class有二個整數變數:分子和分母,和定義了三個Method來對這二個變數做設定其數值,和取其數值印出的功能。 #import <Foundation/Foundation.h> @interface Fraction : NSObject { int numerator; //分子 int denominator; //分母 } -(void) print; //印出分式 -(void) setNumerator:(int) n; //設定分子的method,把分子設定於整數n -(void) setDenominator:(int) d;//設定分子的method,把分母設定於整數d @end @implementation Fraction -(void) print{ NSLog(@"%i/%i",numerator,denominator); } -(void) setNumerator:(int) n{ numerator=n; } -(void) setDenominator:(int) d{ denominator=d; } @end int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *myFraction; myFraction=[Fraction alloc]; myFraction=[myFraction init]; [myFraction setNumerator:1]; [myFraction setDenominator:3]; NSLog(@"分式是"); [myFraction print]; [myFraction release]; [pool drain]; return 0; } 輸出的結果 分式是 1/3 Objective-C的程式碼可以分成三個部分: @interface 部分 @implementation 部分 program 部分 @interface 部分描述了class和它的資料組成及它的method,而@implementation 部分則是對method實際要作的動作做程式碼編寫,而最後program 部分則是讓這個程式表現出最後的結果。 @interface 部分 當定義一個新的class的時候,必須做一些事情。首先,要讓Objective-C 編譯器知道這個class是遺傳自那裡,也就是它的父(母)類別(parent class);其次要定義在這個class的物件中的資料型態組成,所以在這個class中要描述其資料的成員,這些成員就是instance variables;最後,要定義一些操作它的功能,也就是methods。這些描述都在@interface部分中,他一般是這樣的格式: @interface NewClassName: ParentClassName { memberDeclarations; } methodDeclarations; @end 照Objective-C的習慣,class名稱使用開頭為大寫字母的字詞,即使這不是必要的條件。但這樣可以讓人更容易閱讀程式碼,只靠頭的大寫字母就可以區分出是class名稱和其他變數名稱。這裡要談到一點點Objective-C的命名原則。 命名原則 Objective-C的名稱可以以字母或是底線(underscore, “_”)做為開頭,後面可以接上字母組成(大寫或小寫字母),底線,或數字(0﹣9),下面的是正確的名稱: sum, pieceFlag, i, myLocation, numberOfMobes, _sysFlag, ChessBoard, 而這些名稱是不正的: sum$value, $ 不是正確的字元。 piece flag, 中間不能有空格。 3Spencer, 名稱不能以數字開頭。 int , 這是保留字,對編譯器有特殊意義,所以不能拿來使用做為命名用途。 保留字可以查詢Programming in Objective-C 2.0 的附錄。 因為大小寫或底線的組成可以形成各種組成的字,而且sum, Sum, SUM對編譯器來說是不同的字。class名稱會以大寫字母做為開頭,而 method 名稱、變數名稱、物件名稱則以小寫字母做為開頭: AddressBook, 這看起來是個class名稱。 currentEntry, 可能是物件變數名稱。 current_entry, 有些人喜歡且底線來區分字詞。 addNewEntry, 這可能是method名稱。 wheveryoulike, 這可能是某基本資料型態名稱。 物件名稱會以小寫(形容)詞開頭,其他的字詞則用大寫字母,而變數名稱會用小寫字母為主,而method名稱會以動詞開頭。 不要覺得這個很煩,如果有良好的習慣,這樣的程式碼人(包括自已)會容易解讀,也容易管理。 續@interface部分 15.2的程式碼@interface部分: @interface Fraction : NSObject { int numerator; int denominator; } -(void) print; -(void) setNumerator:(int) n; -(void) setDenominator:(int) d; @end 就說明了Fraction class 是繼承 NSObject class (NSObject class 的定義在 NSObject.h檔案內,但開頭的import Foundation.h已把他包含在內),繼承了NSObject class,就表示NSObject class裡面所定義的instances和methods,Fraction class的物件都可以使用。 有二個 instance variables 在 Fraction class中,為二個整數為: int numerator; int denominator; 所以程式是建立了Fraction class的物件,則這兩個變數也會跟著建立。 Class and Instance Methods 必須定義method來對變數或Fraction來做一些事情。print method是把instance variables印成分式: -(void) print; 開頭的負號(“-”)是告訢Objective-C編譯器這個method 是 instance method ,如果是正號(“+”),則為class method,如使class產生新的instance,就是class method。 傳回值: -(void) print; (void)是指這個method沒有傳回值。有的mehtod會有傳回值,如: -(int) getNumerator; 就是定義getNumerator method傳回一個整數值。 -(double) countArea; 定義countArea傳回double資料型態的數值。 而傳回數值,也是指令 return; Method Arguments 如15.2的 -(void) setNumerator: (int) n; -(void) setDenominator: (int) d; method名稱後面的冒號(“:”)表示method要傳一個值給method使用,這個值是整數n。另外一個則是整數d 。 所以一個method的宣告,是包含了方法動類 (method type ( "+" for class method or "-" for instance method)), 傳回值的資料型 (return type),method 名稱 (method name),method帶大輸入資料參數 (method takes arguments),輸入參數的資料型態 (argument type), 參數名稱(argument name)。 這裡我用(-(void)setNumerator:(int)n)這個定義的method來說明: - 指其為 instance method,對象是 instance。 (void) void 為這個method沒有傳回值。 setNumerator method 名稱。 : 這個method有參數要輸入運算。 (int) 這個輸入參數的資料型態為整數。 n 這個輸入參數的名稱。 @implementation部分 如前例: @implementation Fraction -(void) print{ NSLog(@"%i/%i",numerator,denominator); } -(void) setNumerator:(int) n{ numerator=n; } -(void) setDenominator:(int) d{ denominator=d; } @end 解說: @implementation部分的內容就是一些mehtods的實際內容。這部分就像是定義C的函數一樣。 print method 是讓螢幕印出分式,用NSLog()來輸出內容(instance varialbe的值)。 setNumerator method是把整數n存到變數numerator。 setDenominator method是把整數d存到變數denominator。 program的部分 int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *myFraction; myFraction=[Fraction alloc]; myFraction=[myFraction init]; [myFraction setNumerator:1]; [myFraction setDenominator:3]; NSLog(@"分式是"); [myFraction print]; [myFraction release]; [pool drain]; return 0; } NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 這行是產生一個 pool物件,這個物件的功能和記憶體管理有關的,現在先不用管它。 主程式中,定義了myFraction變數: Fraction *myFraction; 這是說:「myFraction 是個 Fraction 型態的物件」。myFraction可用來儲存Fraction class的值,星號(“*”)是必要的,現在我們不用去管它是做什麼用的,術語上來說,myFraction是個Fraction 型態的地址(參考C指標)。 myFraction=[Fraction alloc]; 這行是送一個訊息來產生一個記憶體空間給新的分式物件使用。alloc method是定義在NSObject class中的,因為Fraction class繼承了它,所以也可以使用這個mehtod。 這樣記憶體空間已劃分兩個整數空間給myFraction,但是它可能會是任何值,所以必須要初始化(initialize)後(如將變數歸零)再開始使用: myFraction=[myFraction init]; init method也是定義在NSObject class中。 這二行可以簡化成: myFraction=[[Fraction alloc] init]; 接下來是設定分子、分母的值給myFraction的numerator和denominator二個instance variables: [myFraction setNumerator:1]; 把1存到numerator, [myFraction setDenominator:3]; 把3存到denominator; 然後是印出螢幕的字樣: NSLog(@"分式是"); [myFraction print]; 就是把myFraction裡面的numerator和denominator變數印出。 最後物件不會再使用到以後,就要把它佔的記憶體空還給系統,這一點非常重要。 [myFraction release]; release mehtod也是NSObject class定義的。 下個程式碼是印出兩個分式: #import <Foundation/Foundation.h> @interface Fraction : NSObject { int numerator; int denominator; } -(void) print; -(void) setNumerator:(int) n; -(void) setDenominator:(int) d; @end @implementation Fraction -(void) print{ NSLog(@"%i/%i",numerator,denominator); } -(void) setNumerator:(int) n{ numerator=n; } -(void) setDenominator:(int) d{ denominator=d; } @end int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *frac1=[[Fraction alloc] init]; Fraction *frac2=[[Fraction alloc] init]; [frac1 setNumerator:2]; [frac1 setDenominator:5]; [frac2 setNumerator:3]; [frac2 setDenominator:7]; NSLog(@"第一個分式是"); [frac1 print]; NSLog(@"第二個分式是"); [frac2 print]; [frac1 release]; [frac2 release]; [pool drain]; return 0; } 輸出為 第一個分式是 2/5 第一個分式是 3/7 這個程式是二個物件變數frac1, frac2,可以用想同的mehtod來設定值和印出值。 下例是在Fraction class 中,增加兩個method,功用是可以傳回instance valuable的值。 #import <Foundation/Foundation.h> @interface Fraction : NSObject ... -(int) numerator; -(int) denominator; @end @implementation Fraction ... -(int) numerator{ return numerator; } -(int) denominator{ return denominator; } @end int main (int argc, const char * argv[]) { NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; Fraction *myFraction=[[Fraction alloc] init]; [myFraction setNumerator:1]; [myFraction setDenominator:3]; NSLog(@"這個分式是%i/%i",[myFraction numerator],[myFraction denominator]); [myFraction release]; [pool drain]; return 0; } 輸出為 這個分式是1/3 這個例子是說明可以設定instance variable的method,被稱為設定者(setter);而取得 instance variable的 method ,則稱為取得者(getter)。在Objective-C 2.0 版本中有新的語法可以自動產生getter methods和 setter methods,以後再介紹它。 另外,NSObject class也有定義了一個 new method,可以產生新的instance並且初始化: Fraction *myFraction=[Fraction alloc] init]; 等同於 Fraction *myFraction=[Fraction new]; |
|
( 知識學習|其他 ) |