寫在前面
第一次接觸oc的編程掠剑,由于之前有java 的學習經(jīng)歷屈芜,并且在老師的帶領下,認識了很多關于oc的學習途徑對學習很有幫助朴译。
類與對象
一井佑、面向對象
OC語言是面向對象的,c語言是面向過程的眠寿,面向對象和面向過程只是解決問題的兩種思考方式躬翁,面向過程關注的是解決問題涉及的步驟,面向對象關注的是設計能夠實現(xiàn)解決問題所需功能的類盯拱。
術語:OO面向對象盒发、OOP面向對象編程
二、類和對象
(一)關于類
類的設計只關注三個東西:類名坟乾、屬性和方法
注意:一般名詞都是類迹辐,擁有相同屬性和行為的對象都可以抽象為一個類蝶防,類名是標識符的一種甚侣,需要符合規(guī)范,通常類名的第一個字母大寫间学,且不能有下劃線殷费,如果有多個單詞則使用駝峰標識。在對方法進行類的劃分中低葫,一般采取的做法是誰最熟悉這個方法那么就把這個方法劃分給誰详羡。在OC中,對象對方法的調用稱為消息機制嘿悬,即向既定的對象發(fā)送了什么消息实柠。
(二)簡單內存分析
類創(chuàng)建對象,每個對象在內存中都占據(jù)一定的存儲空間善涨,每個對象都有一份屬于自己的單獨的成員變量窒盐,所有的對象公用類的成員方法草则,方法在整個內存中只有一份,類本身在內存中占據(jù)一份存儲空間蟹漓,類的方法存儲于此炕横。
每個對象內部都默認有一個isa指針指向這個對象所使用的類。
[p?eat];表示給p所指向的對象發(fā)送一條eat消息葡粒,調用對象的eat方法份殿,此時對象會順著內部的isa指針找到存儲于類中的方法,執(zhí)行嗽交。
isa是對象中的隱藏指針卿嘲,指向創(chuàng)建這個對象的類。
常見錯誤
1.類的聲明和實現(xiàn)不能嵌套
2.方法的實現(xiàn)必須放在@implementation中轮纫,不能放在@interface中腔寡。
3.方法聲明不能放在大括號{}里。
4. 聲明新類的時候不能和已有的類嵌套掌唾。
5.不允許在@interface大括號里給成員變量賦值(初始化)放前,也不能隨便將成員變量當作C語言中的變量來使用,如用static修飾糯彬。
6.類的聲明必須放在main函數(shù)前面凭语。
三、方法與函數(shù)
方法與函數(shù)的區(qū)別:
(1)對象方法的聲明必須寫在@interface和@end之間撩扒,對象方法的實現(xiàn)必須寫在@implementation和@end之間
(2)對象方法都以-號開頭似扔,類方法都以+號開頭
(3)對象方法只能由對象來調用,類方法只能由類來調用搓谆,不能當做函數(shù)一樣調用
(4)函數(shù)能寫在文件的任意位置(@interface和@end之間除外)炒辉,函數(shù)歸文件所有
(5)對象方法歸類\對象所有
(6)函數(shù)調用不依賴與對象
(7)函數(shù)內部不能直接通過成員變量名訪問對象的成員變量
屬性和實例變量
一、類Class中的屬性property
在ios第一版中:
我們?yōu)檩敵隹谕瑫r聲明了屬性和底層實例變量泉手,那時黔寇,屬性是oc語言的一個新的機制,并且要求你必須聲明與之對應的實例變量斩萌,例如:
注意:(這個是以前的用法)
@interface MyViewController :UIViewController
{
UIButton *myButton;
}
@property (nonatomic, retain) UIButton *myButton;
@end
在現(xiàn)在iOS版本中:
蘋果將默認編譯器從GCC轉換為LLVM(low level virtual machine)缝裤,從此不再需要為屬性聲明實例變量了。如果LLVM發(fā)現(xiàn)一個沒有匹配實例變量的屬性颊郎,它將自動創(chuàng)建一個以下劃線開頭的實例變量憋飞。因此,在這個版本中姆吭,我們不再為輸出口聲明實例變量榛做。
ios5更新之后,蘋果是建議以以下的方式來使用:
@interface MyViewController :UIViewController
@property (nonatomic, retain) UIButton *myButton;
@end
因為編譯器會自動為你生成以下劃線開頭的實例變量_myButton,不需要自己手動再去寫實例變量检眯。而且也不需要在.m文件中寫@synthesize?myButton升敲,也會自動為你生成setter,getter方法轰传。
@synthesize的作用:(1)讓編譯器為你自動生成setter與getter方法驴党。(2)可以指定與屬性對應的實例變量,例如@synthesize myButton = xxx获茬;那么self.myButton其實是操作的實例變量xxx港庄,而不是_myButton了。
現(xiàn)在:如果.m文件中寫了@synthesize?myButton恕曲,那么生成的實例變量就是myButton鹏氧;如果沒寫@synthesize?myButton,那么生成的實例變量就是_myButton佩谣。所以跟以前的用法還是有點細微的區(qū)別把还。
二、實例變量與屬性變量使用方法
在MyViewController.m文件中茸俭,編譯器也會自動的生成一個實例變量_myButton吊履。那么在.m文件中可以直接的使用_myButton實例變量,也可以通過屬性self.myButton.都是一樣的调鬓。用self.yourButton來訪問yourButton變量是不對的艇炎,Xcode會提示你使用->,改成self->yourButton就可以了。因為OC中點的表達式是表示調用yourButton方法腾窝,而上面代碼沒有yourButton方法缀踪,也可以直接使用yourButton。
三虹脯、類別中的屬性property
類與類別中添加的屬性要區(qū)分開來驴娃,因為類別中只能添加方法,不能添加實例變量循集。經(jīng)常會在ios的代碼中看到在類別中添加屬性唇敞,這種情況下,是不會自動生成實例變量的暇榴。比如在:UINavigationController.h文件中會對UIViewController類進行擴展
@interface UIViewController (UINavigationControllerItem)
@property(nonatomic,readonly,retain) UINavigationItem *navigationItem;
@property(nonatomic) BOOL hidesBottomBarWhenPushed;
@property(nonatomic,readonly,retain) UINavigationController *navigationController;
@end
這里添加的屬性厚棵,不會自動生成實例變量蕉世,這里添加的屬性其實是添加的getter與setter方法蔼紧。
注意一點,匿名類別(匿名擴展)是可以添加實例變量的狠轻,非匿名類別是不能添加實例變量的奸例,只能添加方法,或者屬性(其實也是方法)。
四查吊、成員變量谐区、實例變量、屬性變量的聯(lián)系
@interface MyViewController :UIViewControlle
{
UIButton *yourButton;
int count;
id data逻卖;
}
@property (nonatomic, strong) UIButton *myButton;
@end
在{?? } 中所聲明的變量都為成員變量宋列。 所以yourButton、count评也、data都是成員變量炼杖。既然如此,實例變量又是什么意思呢盗迟?
實例變量本質上就是成員變量坤邪,只是實例是針對類而言,實例是指類的聲明罚缕。{?? }中的yourButton就是實例變量艇纺。id 是OC特有的類,本質上講id等同于(void *)邮弹。所以id data屬于實例變量黔衡。
成員變量用于類內部,無需與外界接觸的變量腌乡。因為成員變量不會生成set员帮、get方法,所以外界無法與成員變量接觸导饲。根據(jù)成員變量的私有性捞高,為了方便訪問,所以就有了屬性變量渣锦。屬性變量的好處就是允許讓其他對象訪問到該變量(因為屬性創(chuàng)建過程中自動產(chǎn)生了set 和get方法)硝岗。當然,你可以設置只讀或者可寫等袋毙,設置方法也可自定義型檀。所以,屬性變量是用于與其他對象交互的變量听盖。
綜上所述可知:成員變量是定義在{}號中的變量胀溺,如果變量的數(shù)據(jù)類型是一個類則稱這個變量為實例變量。因為實例變量是成員變量的一種特殊情況皆看,所以實例變量也是類內部使用的仓坞,無需與外部接觸的變量,這個也就是所謂的類私有變量腰吟。而屬性變量是用于與其他對象交互的變量无埃。
但是,現(xiàn)在大家似乎都不怎么喜歡用成員變量來定義類的變量,都喜歡用屬性變量來定義類的變量嫉称。把需要與外部接觸的變量定義在.h文件中侦镇,只在本類中使用的變量定義在.m文件中。
方法
方法是Objective-C獨有的一種結構织阅,只能在Objective-C中聲明壳繁、定義和使用,C語言不能聲明荔棉、定義和使用氮趋。
1、類方法以+號開頭江耀,對象方法以-號開頭
+ (void) init;? ?? ???// 類方法
- (void) show;? ?? ?? ?? ?? ? // 對象方法
2剩胁、在@interface和@end之間聲明,在@implementation和@end之間定義
@interface Test : NSObject
// 方法聲明
+ (void) init;
- (void) show;
@end
@implementation Test
// 方法實現(xiàn)
+ (void) init
{
}
- (void) show
{
}
@end
3祥国、類方法只能由類來調用昵观,對象方法只能由方法來調用
// 調用類方法
[Test init];
// 調用對象方法
Test *t = [Test new];
[t show];
4、方法歸類舌稀、對象所有啊犬。
5、方法聲明和實現(xiàn)中用到的數(shù)據(jù)類型必須用()括住壁查。
函數(shù):函數(shù)即C語言中的函數(shù)觉至,在C和Objective-C中都聲明、定義和使用睡腿。
1语御、函數(shù)能寫在文件中的任意位置(@interface和@end之間除外),函數(shù)歸文件所有席怪。
int add(int num1, int num2)
{
return num1 + num2;
}
2应闯、函數(shù)調用不依賴于對象。
int sum = add(1, 2);
3挂捻、函數(shù)內部不能直接通過成員變量名訪問某個對象的成員變量碉纺。
初始化器和析構器
初始化器:init
對象初始化器: -(id)init 可以重載多個。
類型初始化器: +(id)initialize只能有一個刻撒。
對象初始化器:
初始化對象實例時骨田,init通常和alloc(手動內存分配)搭配使用。
alloc所做的事情——NSObject已實現(xiàn)声怔。
·在堆上分配合適大小的內存态贤。
·將屬性或者實例變量的內存置0。
init所做的事情——可以自定義:
·調用父類初始化器[super init](前置調用)
·初始化當前對象的實例變量(注意是實例變量捧搞,不是屬性)
new 相當于調用alloc/init的無參數(shù)版本抵卫。
·Book* book = [Book new];
類初始化器:一般用的很少
比如說類里有一個全局的靜態(tài)變量胎撇,就需要在類初始化的時候賦個初值介粘。
initialize在每個類使用之前被系統(tǒng)自動調用,且只調用一次(每個進程周期)晚树。
子類的initialize會自動調用父類的initialize(前置調用)姻采。
析構器:dealloc(也叫釋放器)
釋放對象所擁有的資源,無返回值的函數(shù)爵憎。
只有對象析構器慨亲,沒有類型析構器。
自動實現(xiàn):1.ARC將對象屬性引用計數(shù)減持宝鼓。
手動實現(xiàn):2. 釋放不受ARC管理的動態(tài)內存刑棵,如malloc分配的內存。
手動實現(xiàn):3. 關閉非內存資源愚铡,如文件句柄蛉签,網(wǎng)絡接口。沥寥。碍舍。
dealloc由ARC根據(jù)對象引用計數(shù)規(guī)則,在釋放對象內存前自動調用邑雅,無法手動調用片橡。
子類的dealloc會自動調用父類的dealloc(后置調用)。
繼承和多態(tài)
1淮野、繼承
繼承的好處:
創(chuàng)建大量的相似類的時候捧书,可以節(jié)省工作量。
使用框架中的類骤星,或已經(jīng)寫好的類鳄厌,繼承該類,生成一個派生類妈踊,比原類更好用了嚎。
重寫(繼承的另一部分)
子類可以從父類繼承方法,但是有時候父類的方法不適合子類廊营,子類就可以寫一個自己的同名方法歪泳,覆蓋掉父類的同名方法,叫做重寫露筒。
重寫的時候呐伞,在子類的.h中不必重新聲明,直接在.m中寫實現(xiàn)就可以慎式。
2伶氢、多態(tài)
多態(tài)在代碼中的體現(xiàn)趟径,即為多種形態(tài),必須要有繼承癣防,沒有繼承就沒有多態(tài)蜗巧。
在使用多態(tài)是,會進行動態(tài)檢測蕾盯,以調用真實的對象方法幕屹。
多態(tài)在代碼中的體現(xiàn)即父類指針指向子類對象。(*)
參考資料:
http://www.cnblogs.com/xiaodong208/p/4233025.html
http://www.cnblogs.com/FightingLuoYin/p/4341340.html
http://www.bkjia.com/IOSjc/1126149.html