Objective-C作為一種面向對象的編程語言, 具有面向對象的基本特征,?
即: 封裝、 繼承和多態。?
主要介紹ObjectiveC中有關面向對象基本概念: 類、 對象、 方法和屬性等。
也就是面向對象程序設計的一些關鍵概念,主要關注Objective-C定義類相關的語法。
OC面向對象方面的概念和其它語言差不多。相比其他語言更接近C++。
對象就是一個物件。面向對象的程序設計可以看成一個物件和你想對它做的事情。
對象(名詞)----實現(動詞),先定義類(Class),再定義方法(Method)。
#### C語言是典型的面向過程性語言。
在C語言中,通常是先考慮要實現什么,然后才關注對象,這幾乎總是與面向對象的思考過程相反。
實現(動詞)----對象(名詞),先定義函數(Function),再定義模塊(Module)。
類的獨特存在就是一個實例,對實例執行的操作稱為方法。
在某些情況下,方法可以應用于類的實例或類本身。
對象使用方法可以影響對象的狀態。
關鍵概念:對象是類的獨特表示,每個對象都包含一些通常對該對象來說是私有的信息(數據)。方法提供訪問和改變這些數據的手段。
Objective-C采用特定的語法對類和實例應用方法:
[ ClassOrInstance method];
請求一個類或實例來執行某個操作時,就是向它發送一條消息,消息的接收者稱為Receiver。所以,可以用另外一種方式描述:
[ receiver message];
Objective-C的Method操作執行,一種理解是發送消息,另外一種是方法調用。
前一種更貼近OC的思想。
Objective-C的類聲明和實現包括兩個部分:接口部分和實現部分。
~~~
@interface Song: NSObject {
… …
}
… …
@end
@implementation Song
… …
@end
~~~
同樣的,程序在邏輯上就分為下面3個部分:
@interface
@implementation
program
#### 接口部分
@interface部分用于描述類和類的方法;
@implementation部分用于描述數據(類對象的實例變量存儲的數據),并實現在接口中聲明方法的實際代碼;
主要定義了類名 、 繼承的父類、 實現的協議、 成員變量和方法等信息。
舉例如下:
一首好聽的音樂,下面的代碼是Song類的接口部分聲明。
~~~
@interface Song : NSObject {
NSString *title;
NSString *artist;
long int duration;
}
- (void)start;
- (void)stop;
- (void)seek:(long int)time;
@end
~~~
program部分的程序代碼實現了程序的預期目的。
@interface部分一般格式如下:
@interface NewClassName: ParentClassName
propertyAndMethodDeclarations;
@end
按照約定,類名以大寫字母開頭。
實例變量、對象以及方法的名稱,通常以小寫字母開頭。
確定名稱時,要遵循找到能反映變量或對象使用意圖的名稱。
程序具有更強的自解釋性(Self-explanatory)
制定名稱的規則相當簡單:名稱必須以字母或下劃線(_)開頭,
之后可以使任何大小寫字母、下劃線或者數字的組合。
另外像$空格等都是非法,記住不能數字開頭、不能使用保留字。
再次強調,Objective-C是大小寫敏感的。sum、Sum、SUM均表示不同的變量。
#### 實現部分
使用關鍵字@implementation, 主要實現了在接口部分定義的方法等信息。?
~~~
@implementation部分的一般格式如下:
@inplementation NewClassName
{
memberDeclarations;
}
methodDefinitions;
@end
~~~
需要注意的是:使用@synthesize指令能讓編譯器自動為你生成一些方法。
舉例如下:
下面的代碼是Song類的實現部分聲明。
~~~
@implementation Song
- (void)start {
//開始播放
}
- (void)stop {
//停止播放
}
- (void)seek:(long int)time {
//跳過時間
}
@end
~~~
接口和實現的要求:
接口文件包含類的公開信息,即能夠與這個類的使用者共享一些信息。
另一方面,實現部分包含的是私有信息,即實例變量和代碼。
#### 方法和消息
類或實例方法,開頭為負號(-)表示實例方法,正號(+)表示類方法。
返回類型放在開頭的負號或正號之后的圓括號中。
有參數時,在方法名后加冒號(:),再加上參數類型和參數名。
具體的如下例所示:
-(int) currentAge;
-(void) print;
-(void) setNumber: (int) n;
方法類型 (返回類型) 方法名稱 方法有參數 參數類型 參數名稱
可見,Objective-C中方法定義非常古怪, 它遵循了SmallTalk語法風格, 它將一個方法名字分成幾個部分。

如圖所示:

再次解釋說明:
定義了兩個參數的方法,?
第一個參數是anObject, 參數類型是id類型,?
第二個參數是index, 參數類型是NSUInteger,
這叫做多重參數。?
它的返回類型是void,?
方法簽名是insertObject:atIndex: 。?
方法類型標識符中都“-” 代表方法是實例方法, “+” 代表方法是類方法,
?關于實例方法和類方法我們將在后面內容中討論。?
如果上面的方法變成C或C++形式, 則是下面的樣子的:?
-(void) insertObjectAtIndex(id anObject, NSUInteger index)。
#### 消息發送
對于方法的調用通常也不稱之為調用 , 而是稱為發出消息,
操作符號不是“. ” 而是“[…] ” , 如下所示:?
[myObject insertObject: ojb1 atIndex:0];
即向myObject對象發出一個消息insertObject:atIndex: 。
而在實際使用時候這兩種叫法都會用 , 這不是嚴格劃分。
alloc是allocate的縮寫。
如果向某個類發送alloc消息,便獲得該類的新實例。
這個alloc方法繼承自父類。alloc方法保證對象的所有實例都變成初始狀態。
當然想要適當的方法時,必須重新初始化,調用init方法。
經常地情況是把alloc和init合在一起,或者直接使用new方法。
例如:
~~~
Fraction?*myFraction;??
myFraction?=?[Fraction?alloc];//類方法??
myFraction?=?[myFraction?init];//實例方法??
??
Fraction?*myFraction?=?[[Fraction?alloc]?init];//二合一??
??
Fraction?*myFraction?=?[Fraction?new];//類方法,new包含alloc和init??
~~~
記住,方法執行的上下文環境就是接收到消息的對象。
取值方法(get)和賦值方法統(set)稱為訪問方法(accessor)。
這就是數據封裝的原則,通過使用方法來訪問對“外界”隱藏的數據。
使用一個類的程序結束本章:
~~~
//??
//??main.m??
//??3_2_class_object_method??
//??
//??Created?by?haomengzhu?on?14-11-01.??
//??Copyright?(c)?2014年?haomengzhu.?All?rights?reserved.??
//??
??
#import???
??
//--------?@interface?section?----------??
@interface?Fraction:?NSObject??
-(void)?print;??
-(void)?setNumerator:?(int)?n;??
-(void)?setDenominator:?(int)?d;??
@end??
??
//--------?@implementation?section?----------??
@implementation?Fraction??
{??
????int?numerator;??
????int?denominator;??
}??
-(void)?print??
{??
????NSLog(@"%i/%i",?numerator,?denominator);??
}??
-(void)?setNumerator:(int)n??
{??
????numerator?=?n;??
}??
-(void)?setDenominator:(int)d??
{??
????denominator?=?d;??
}??
@end??
??
//--------?program?section?----------??
??
int?main(int?argc,?const?charchar?*?argv[])??
{??
??
????@autoreleasepool?{??
????????Fraction?*myFraction;??
??????????
????????//?new?object??
????????myFraction?=?[Fraction?alloc];??
????????myFraction?=?[myFraction?init];??
??????????
????????//?set??
????????[myFraction?setNumerator:?1];??
????????[myFraction?setDenominator:?3];??
??????????
????????//?print?all??
????????NSLog(@"Hello,?World!");??
????????[myFraction?print];??
????}??
????return?0;??
}??
~~~
最后再來說說OC中的方法:
#### 關于方法:
在編寫新方法時,省略參數名不是一種好的編程風格,因為它是程序很難讀懂并且很不直觀,
特別是當使用的方法參數特別重要時,更是如此。
舉例如下:
定義了Fraction類以及新方法:
-(void)setTo:(int)n over:(int)d;?
注意下面的使用方式:
[aFraction set:1 :3]這是不好的
[aFraction set:1 over:3]這是好的
#### 再添加新方法:
- (void)add:(Fraction *) f;
這條語句說明add:方法的參數是Fraction類對象的一個引用。
星號是必須的,所以聲明(Fraction) f是不正確的。
#### 局部變量:
局部變量是基本的C數據類型,并沒有默認的初始值,所以在使用前要先賦值。
局部對象變量默認初始化為nil。
和實例變量不同(它們在多次方法調用時保持自己的值),這些局部變量沒有記憶力。
也就是說,當方法返回時,這些變量的值都消失了。
每次調用方法時,該方法中的局部變量都使用變量聲明重新初始化一次。
#### 方法的參數:
方法的參數名也是局部變量。執行方法時,通過方法傳遞的任何參數都被復制到局部變量中。因為方法使用參數的副本,所以不能改變通過方法傳遞的原值。這一點很重要。
另外,如果參數是對象,可以更改其中的實例變量值。當你傳遞一個對象作為參數時,實際上是傳遞了一個數據存儲位置的引用。正因為如此,你才能夠修改這些數據。
#### static關鍵字:
在變量聲明前加上關鍵字static,可以使局部變量保留多次調用一個方法所得的值。
和其它基本數據類型的局部變量不同。
靜態變量的初始值為0。
此外,它們只在程序開始執行時初始化一次,并且在多次調用方法時保存這些數值。
記住:只能在定義靜態變量和局部變量的方法中訪問這些變量。