英漢詞典推薦:歐路詞典
開發(fā)注意:開發(fā)中盡量讓錯誤發(fā)生在編譯時,不要發(fā)生在運行時!
類回顧:
屬性就是專門儲存數(shù)據(jù)的
屬性(成員變量)的命名以下劃線開頭的好處:可以區(qū)分屬性和局部變量
super并不是關(guān)鍵字,而是編譯器的指令符號:
self的用法:與super相似,調(diào)用除了自己以外的父類們的方法(而self則是調(diào)用自身坐在的類中的方法)
為什么要用super:如果需要在子類中調(diào)用父類的方法可以用super
注意:在當前方法內(nèi)使用self調(diào)用當前方法名的方法會造成死循環(huán),但是super不會(super只會向上級找,終會有停止的時候)
應(yīng)用場景:重寫父類的方法,并且需要保留父類方法中的功能,這種情況使用super
面向?qū)ο蟮谌筇匦?多態(tài):
多態(tài)是指:事物的多種表現(xiàn)形態(tài)
編譯:在一個父類中使用多態(tài)指向子類并調(diào)用子類的方法時,編譯器會先在這個父類中找有沒有聲明和實現(xiàn)同名的方法(也就是說:子類必須重寫父類的方法),如果沒有聲明則編譯報錯(如果只聲明沒有實現(xiàn),編譯器會報警告),如果有聲明和實現(xiàn)則可以進行編譯.
運行:運行的時候會按照子類中的方法執(zhí)行
父類使用多態(tài)調(diào)用子類特有方法的解決辦法:可以通過強制類型轉(zhuǎn)換解決父類調(diào)用子類特有方法的問題,如下:
Animal*ani2 = [[Catalloc]init];
Cat*c = (Cat*)ani2;//強制類型轉(zhuǎn)換為Cat類型
[cclamb];//調(diào)用Cat中的特有方法
使用多態(tài)的優(yōu)點:提高了代碼的拓展性
實例變量(成員變量)的修飾符:
作用域:從出現(xiàn)的位置開始直到遇到下一個修飾符或大括號結(jié)束
@public:可以在其他類中訪問,也可以在本類中訪問,也可以在子類中訪問
@private(私有的)(默認情況下,在@implement中定義的屬性都是private的(純私有),而且定義在@implement中定義的私有變量,外界看都看不到,子類也不會擁有):不可以在其他類中訪問,可以在本類中訪問,不可以在子類中訪問(只要繼承就會擁有,但是擁有不一定可以訪問)
@protected(默認情況下,在@interface中定義的所有的屬性都是protected):不可以在其他類中訪問,可以在本類中訪問,也可以在子類中訪問
@package:介于private與public之間,在當前包里就是public類型的,在其他包里就是private類型的
description:
只要使用%@打印對象名稱,就會默認調(diào)用-的description方法,使用%@打印類對象名稱,就是調(diào)用+的description方法,想打印對象(或類)的信息就在類中重寫description方法,里面寫上要打印的內(nèi)容
建議:在description方法中盡量不要使用self,在description中使用%@打印self會造成死循環(huán)
class方法:給類發(fā)送class消息就會返回當前類的名字
私有方法的定義:如果方法只有聲明,沒有實現(xiàn),就稱為這個方法是私有方法(OC中沒有真正的私有方法)
@property(重點):
@property是一個編譯器指令(與預(yù)處理指令一樣):編譯器會在編譯的時候?qū)proberty替換成某一段代碼
注意:4.4之前只可以使用@property代替getter和setter方法的聲明
@property的書寫規(guī)范:@property int age;
@property替代setter-getter聲明的方式:
@propertyintage;
- (void)setAge:(int)age;
- (int)age;
//Xcode4.4之前編譯器會在編譯的時候?qū)⒌谝欢未a轉(zhuǎn)換為第二段代碼和第三段代碼
@synthesize也是一個編譯器指令:
@synthesize的書寫規(guī)范:@synthesize age = _age;
如果synthesize后面只寫了age(例如:synthesize age;)那么用戶賦值與取值的操作都是針對age的,而不是_age
加強版@property:
Xcode4.4之后@property可以直接生成setter和getter方法的聲明和實現(xiàn)
加強版@property的書寫規(guī)范與普通@property的書寫方式相同:
@propertyintage;//這一句代碼代替了原來getter-setter的四段代碼(兩個聲明,兩個實現(xiàn)),并且同時生成了一個純私有的變量_age
@property會將值賦給下劃線開頭的變量(而不是同名變量,與@synthesize有區(qū)別)
@property的弊端:他只會生成最簡單的getter和setter方法,并不會對傳入的數(shù)據(jù)進行過濾/監(jiān)控等操作,如果需要對數(shù)據(jù)進行過濾,那么需要重寫setter和getter方法
已有@property已經(jīng)存在的情況下,重寫setter-getter:
只重寫setter方法,那么編譯器會自動生成一個getter方法,并且自動生成私有變量
只重寫getter方法,那么編譯器會自動生成一個setter方法,并且自動生成私有變量
但是如果同時重寫getter方法和setter方法,那么編譯器不會自動生成成員變量!
增強@property這段代碼在編譯的時候做了三件事:
生成實例變量
生成setter_getter聲明
生成setter_getter方法的實現(xiàn)
@property的修飾符:
定義一個屬性的完整格式:@property(修飾符) 屬性類型 屬性名稱;
readonly(只讀):值生成getter方法,不生成setter方法
readwrite(可讀可寫):既生成setter方法,也生成getter方法
沒有只寫的修飾符,如果需要,自己手寫
另外還可以在(修飾符)的位置寫上重命名的getter方法或setter方法,如下
@property(getter= isMarried)intmarried;//這樣定義后,我們?nèi)匀豢梢岳胹etMarried給_married賦值,但是如果需要取值的話,就需要通過isMarried方法了,而不是married方法
id類型(id類型是一個動態(tài)數(shù)據(jù)類型):
默認情況下所有的數(shù)據(jù)都是靜態(tài)數(shù)據(jù)類型
靜態(tài)數(shù)據(jù)類型:在編譯的時候就知道這個變量屬于什么類型,包含哪些屬性和方法,如果訪問了不屬于自己的方法或?qū)傩?那么編譯器在編譯的時候回報錯
動態(tài)數(shù)據(jù)類型:在編譯的時候編譯器不知道這個變量的真是類型,所以如果這個變量訪問了不屬于自己的屬性或方法,編譯器也不會報錯
id的本質(zhì):id == NSObject *
NSObject *與id的區(qū)別:
NSObject * 是一個靜態(tài)數(shù)據(jù)類型,id是一個動態(tài)數(shù)據(jù)類型
通過靜態(tài)數(shù)據(jù)類型定義變量不可以調(diào)用子類特有的方法
動態(tài)數(shù)據(jù)類型在定義變量的時候可以調(diào)用子類特有的方法
動態(tài)數(shù)據(jù)類型的弊端:由于動態(tài)數(shù)據(jù)類型可以調(diào)用任意一個方法,有可能調(diào)用到不屬于自己的方法,編譯器不會報錯,可能導(dǎo)致運行時的錯誤
id的應(yīng)用場景:一般用在多態(tài),可以減少代碼量,避免調(diào)用子類特有方法需要強制類型轉(zhuǎn)換
如何避免動態(tài)數(shù)據(jù)類型引發(fā)運行時的錯誤:一般情況下,如果使用動態(tài)數(shù)據(jù)類型定義一個變量,在調(diào)用這個變量的方法之前會進行一個判斷,判斷當前變量是否能夠調(diào)用這個方法,例如:
idstu3 = [[Studentalloc]init];//定義一個動態(tài)的對象stu3
if([stu3isKindOfClass:[Studentclass]])//判斷stu3是否屬于Student類或Student類的子類,注意isKindOfClass的返回值是一個BOOL類型,class方法是生成一個類的類對象,例如[Person class]就是生成Person的類對象
{
//表達式
}
idstu3 = [[Studentalloc]init];
if([stu3isMemberOfClass:[Studentclass]])//判斷stu3是否屬于Student類
{
//表達式
}
擴展:
[PersonisMemberOfClass:[Studentclass]]//判斷Person是不是Student的子類
new方法的實現(xiàn)原理:
new: ? ? ? ? ? ? ? ? ? ? ? ? (從今以后不能使用new了)
alloc + init: ? ? ? ? ? ? ? (建議以后都使用這種方法創(chuàng)建對象,可以統(tǒng)一編碼格式)
OC中是偽構(gòu)造方法
構(gòu)造方法的用途:用于初始化一個對象
重寫init方法必須按照蘋果規(guī)定的格式寫:
使用self初始化父類
判斷父類是否初始化成功
成功的話,初始化子類的值
返回地址:return self;
重寫init的簡化寫法(最常用):
- (instancetype)init
{
if(self= [superinit]) {
_cli= [[Clipalloc]init];
}
returnself;
}