網路城邦
上一篇 回創作列表 下一篇   字體:
印出分式的程式
2011/02/17 09:16:44瀏覽940|回應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];
( 知識學習其他 )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=paraquat&aid=4893674

 回應文章


等級:
留言加入好友
2012/04/26 17:14
很好的一篇教學文呀!! 學了很多! 加油!!