定義: id是一個(gè)數(shù)據(jù)類型, 并且是一個(gè)
動(dòng)態(tài)數(shù)據(jù)類型
-
作用
- 1.定義變量
- 2.作為函數(shù)的參數(shù)
- 3.作為函數(shù)的返回值
補(bǔ)充:靜態(tài)數(shù)據(jù)類型 默認(rèn)情況下所有的數(shù)據(jù)類型都是靜態(tài)數(shù)據(jù)類型
-
靜態(tài)數(shù)據(jù)類型的特點(diǎn):
- 在編譯時(shí)就知道變量的類型,
- 知道變量中有哪些屬性和方法
- 在編譯的時(shí)候就可以訪問這些屬性和方法,
- 通過靜態(tài)數(shù)據(jù)類型定義變量, 如果訪問了不屬于靜態(tài)數(shù)據(jù)類型的屬性和方法, 那么編譯器就會(huì)報(bào)錯(cuò)
-
動(dòng)態(tài)數(shù)據(jù)類型的特點(diǎn):
- 在編譯的時(shí)候編譯器并不知道變量的真實(shí)類型, 只有在運(yùn)行的時(shí)候才知道它的真實(shí)類型
- 通過動(dòng)態(tài)數(shù)據(jù)類型定義變量, 如果訪問了不屬于動(dòng)態(tài)數(shù)據(jù)類型的屬性和方法, 編譯器不會(huì)報(bào)錯(cuò)
-
動(dòng)態(tài)數(shù)據(jù)類型與靜態(tài)數(shù)據(jù)類型的區(qū)別:
- 通過靜態(tài)數(shù)據(jù)類型定義變量, 不能調(diào)用子類特有的方法
- 通過動(dòng)態(tài)數(shù)據(jù)類型定義變量, 可以調(diào)用子類特有的方法
- 通過動(dòng)態(tài)數(shù)據(jù)類型定義的變量, 可以調(diào)用私有方法
動(dòng)態(tài)數(shù)據(jù)類型的弊端: 由于動(dòng)態(tài)數(shù)據(jù)類型可以調(diào)用任意方法, 所以
有可能調(diào)用到不屬于自己的方法, 而編譯時(shí)又不會(huì)報(bào)錯(cuò), 可能導(dǎo)致運(yùn)行時(shí)的錯(cuò)誤
動(dòng)態(tài)數(shù)據(jù)類型應(yīng)用場(chǎng)景: 多態(tài), 可以減少代碼量, 避免調(diào)用子類特有的方法需要強(qiáng)制類型轉(zhuǎn)換
-
id和NSObject * 的區(qū)別:
- id == NSObject * 兩者都是萬能指針
- NSObject *是一個(gè)靜態(tài)數(shù)據(jù)類型, id是一個(gè)動(dòng)態(tài)數(shù)據(jù)類型
-
注意: 為了避免動(dòng)態(tài)數(shù)據(jù)類型引發(fā)的運(yùn)行時(shí)的錯(cuò)誤, 一般情況下如果使用動(dòng)態(tài)數(shù)據(jù)類型定義一個(gè)變量, 在調(diào)用這個(gè)對(duì)象的方法之前會(huì)進(jìn)行一次判斷, 判斷當(dāng)前對(duì)象是否能夠調(diào)用這個(gè)方法
- 判斷方法1: isKindOfClass 判斷指定的對(duì)象是否是某一個(gè)類, 或者是某一個(gè)類的子類
- 判斷方法2: isMemberOfClass 判斷指定的對(duì)象是否是 當(dāng)前指定的類的實(shí)例
代碼示例如下
id obj = [Student new];
/*
if ([obj isKindOfClass:[Student class]]) {
// isKindOfClass , 判斷指定的對(duì)象是否是某一個(gè)類, 或者是某一個(gè)類的子類
[obj eat];//調(diào)用方法
}
*/
if ([obj isMemberOfClass:[Student class]]) {
// isMemberOfClass : 判斷指定的對(duì)象是否是當(dāng)前指定的類的實(shí)例
[obj eat];//調(diào)用方法
}
-
id
和instancetype
的區(qū)別- 都是萬能指針, 都能指向一個(gè)對(duì)象
- id在編譯的時(shí)候不能判斷對(duì)象的真實(shí)類型, instancetype在編譯的時(shí)候可以判斷對(duì)象的真實(shí)類型
- id可以用來定義變量, 可以作為返回值, 可以作為形參, instancetype只能用于作為返回值
-
自定義構(gòu)造方法使用instancetype
, 不要使用id