面向?qū)ο蟮娜筇卣鳎?/h1>
成員變量的封裝掀宋、繼承天梧、多態(tài)
1.成員變量的封裝 encapsulation : setter
getter
方法
-
好處:意義在于保護(hù)盔性、防止,代碼或數(shù)據(jù)呢岗,被我們無(wú)意中破壞
- 過濾不合理的值
- 屏蔽內(nèi)部的賦值過程
- 讓外界不必關(guān)心內(nèi)部的細(xì)節(jié)
-
setter
方法- 作用:提供一個(gè)方法給外界設(shè)置成員變量值冕香,可以在方法里面對(duì)參數(shù)進(jìn)行相應(yīng)過濾
- 命名規(guī)范:
1> 返回值一定是 void
2> 方法名必須以 set 開頭
3> set后面跟上成員變量的名稱,成員變量的首字母必須大寫
4> 一定要接收一個(gè)參數(shù)后豫,而且參數(shù)類型跟成員變量類型一致
5> 形參的名稱不能跟成員變量名一樣
-
getter
方法- 作用:返回對(duì)象內(nèi)部的成員變量
- 命名規(guī)范
1> 肯定有返回值悉尾,返回值類型肯定與成員變量類型一致
2> 方法名跟成員變量名一樣
3> 不需要接收任何參數(shù)
-
成員變量
- 命名規(guī)范:一定要以下劃線
_
開頭 - 作用
1> 讓成員變量
和getter
方法的名稱區(qū)分開
2> 可以跟局部變量
區(qū)分開,一看到下劃線_
開頭的變量挫酿,一般都是成員變量
- 命名規(guī)范:一定要以下劃線
@interface VampireJune : NSObject
{
// 成員變量盡量不要用 @public
// @public
int _age;
}
// setter 方法 聲明
- (void)setAge:(int)age;
// getter 方法 聲明
- (int)age;
@end
@implementation VampireJune
// setter 方法 實(shí)現(xiàn)
- (void)setAge:(int)age
{
// 這里可以對(duì)傳進(jìn)來的參數(shù)進(jìn)行過濾
_age = age;
}
// getter 方法 實(shí)現(xiàn)
- (int)age
{
return _age;
}
@end
-
動(dòng)態(tài)檢測(cè)
- OC是在運(yùn)行過程中才會(huì)檢測(cè)對(duì)象有沒有實(shí)現(xiàn)相應(yīng)的方法
-
類方法
都是以加號(hào)
+
開頭只能由
類名
來調(diào)用類方法
中不能訪問成員變量(實(shí)例變量)
可以允許
類方法
和對(duì)象方法
同名對(duì)象方法
中可以調(diào)用類方法
-
類方法
的好處和使用場(chǎng)合- 不依賴于對(duì)象构眯,執(zhí)行效率高
- 能用
類方法
,盡量用類方法
-
場(chǎng)合
:當(dāng)方法內(nèi)部不需要使用到成員變量
時(shí)早龟,就可以改為類方法
@interface VampireJune : NSObject
- (void)run;
@end
@implementation VampireJune
- (void)run
{
// 執(zhí)行一些代碼
}
@end
int main()
{
// 調(diào)用 run 類方法
[Person run];
return 0;
}
-
self
指針 : 指向了當(dāng)前方法調(diào)用者
-
誰(shuí)調(diào)用了當(dāng)前方法惫霸,
self
就代表誰(shuí)-
self
出現(xiàn)在對(duì)象方法
中猫缭,self
就代表對(duì)象
-
self
出現(xiàn)在類方法
中,self
就代表類
-
-
使用細(xì)節(jié)
- 在
對(duì)象方法
利用self->成員變量名
訪問當(dāng)前對(duì)象內(nèi)部的成員變量 -
[self 方法名]
可以調(diào)用其他對(duì)象方法\類方法
-
出現(xiàn)的地方
:所有OC方法中(對(duì)象方法\類方法
)壹店,不能出現(xiàn)在函數(shù)里
- 在
當(dāng)
成員變量
和局部變量
同名時(shí)猜丹,采取就近原則,訪問的是局部變量
用
self
訪問成員變量
硅卢,區(qū)分同名的局部變量
-
注
:對(duì)象方法中 可以使用類方法 I渲稀!但不能
使用 self
調(diào)類方法将塑,會(huì)造成死循環(huán)
2.繼承 inheritance :類與類之間的關(guān)系
-
繼承
是一種語(yǔ)法 - 單繼承
- 基本上所有
類
的根類
都是NSObject
-
@interface
類名 后面的冒號(hào):
就是繼承[英文冒號(hào)] - 父類/超類:
superclass
- 子類:
subclass/subclasses
@interface VampireJune : NSObject // 繼承自 NSObject 類
@end
-
好處
- 抽取重復(fù)代碼
- 建立了
類
之間的關(guān)系 -
子類
可以擁有父類
中的所有
成員變量和方法
-
壞處
- 耦合性太強(qiáng) [當(dāng)
父類
沒有了脉顿,子類
就不能用了]
- 耦合性太強(qiáng) [當(dāng)
注意點(diǎn)
1.重寫
:子類
重寫實(shí)現(xiàn)父類
中的某個(gè)方法,覆蓋父類
以前的做法
2.父類
必須聲明在子類
的前面
3.子類
不能擁有和父類
相同名稱的成員變量
4.調(diào)用某個(gè)方法
時(shí)抬旺,優(yōu)先去當(dāng)前類
中找弊予,如果找不到,去父類
中找
5.類方法
同 4. 理-
使用場(chǎng)合
- 當(dāng)兩個(gè)
類
擁有相同
屬性和方法時(shí)开财,就可以將相同的東西抽取到一個(gè)父類
中 - 當(dāng)
A類
擁有B類
中的部分屬性和方法時(shí),可以考慮讓B類
繼承A類
- 當(dāng)
B
是A
時(shí)误褪,即A``B
是同一類型物體责鳍,如,A``B
均是人兽间,或均是動(dòng)物 - 繼承:B 是 A
- 組合:B 擁有 A
- 當(dāng)兩個(gè)
- 繼承 :
@interface A : NSObject
{
int _age;
}
@end
@interface B : A
{
int _weight;
}
@end
- 組合 :
@interface A : NSObject
{
int _age;
}
@end
@interface B : NSObject
{
A *_a;
int _weight;
}
@end
-
super
- 作用
- 直接調(diào)用
父類
的某個(gè)方法 -
super
處在對(duì)象方法
中历葛,就會(huì)調(diào)用父類
的對(duì)象方法
-
super
處在類方法
中,就會(huì)調(diào)用父類
的類方法
- 直接調(diào)用
- 作用
-
使用場(chǎng)合
-
子類
重寫父類
的方法時(shí)嘀略,保留父類
的方法恤溶,不完全覆蓋
-
3.多態(tài) Polymorphism :多種形態(tài)
- 沒有
繼承
就沒有多態(tài)
-
代碼
的體現(xiàn):父類
類型的指針
指向子類對(duì)象
@interface Animal : NSObject
- (void)eat;
@end
@implementation Animal
- (void)eat
{
NSLog(@"------%@------吃東西------",self);
}
@interface Dog : Animal
- (void)run; // Dog 特有的方法,父類 Animal 沒有帜羊,驗(yàn)證多態(tài)局限性
@end
@implementation Dog
- (void)run
{
NSLog(@"------Dog------跑起來------");
}
- (void)eat
{
NSLog(@"------Dog------吃東西------");
}
@end
int main()
{
Dog *d = [Dog new]; // Dog 類型
// 多態(tài) :`父類指針`指向`子類對(duì)象`
Animal *a = [Dog new];
// 調(diào)用方法時(shí)咒程,會(huì)檢測(cè)對(duì)象的真實(shí)類型(這就是動(dòng)態(tài)檢測(cè))
[a eat];
// 這也是多態(tài)
NSObject *n = [Dog new];
NSObject *n2 = [Animal new];
// 這樣是不合理的,OC是弱語(yǔ)法讼育,雖然編譯器不報(bào)錯(cuò)帐姻,只是警告,但是也不要這么寫
// Dog *d = [Animal new];
return 0;
}
- 好處
- 如果
函數(shù)\方法
參數(shù)中使用的是父類類型
奶段,可以傳入父類饥瓷、子類對(duì)象
- 如果
@interface Cat : Animal
@end
@implementation Cat
- (void)eat
{
NSLog(@"------Cat------吃東西------");
}
@end
// 專門用來喂動(dòng)物的函數(shù)
void feed (Animal *a)
{ // 如果參數(shù)中使用的是父類類型,可以傳入父類痹籍、子類對(duì)象
[a eat];
} // 只寫一個(gè)方法呢铆,節(jié)省了寫多個(gè)方法的代碼
int main()
{
Animal *a = [Animal new];
feed(a);
Dog *d = [Dog new];
feed(d);
Cat *c = [Cat new];
feed(c);
return 0;
}
- 局限性
-
父類類型
的變量 不能 直接調(diào)用子類
特有的方法 - 必須
強(qiáng)轉(zhuǎn)
為子類類型
變量后,才能直接調(diào)用子類
特有的方法
-
int main()
{
// 使用多態(tài) 調(diào)用 `run` 方法
Animal *a = [Dog new];
// [a run]; // 從語(yǔ)法角度上蹲缠,這樣不合理
// 編譯器肯定先去 `Animal` 里找 `run` 方法
// 編譯器找不到 `run` 方法棺克,只報(bào)出一個(gè)警告
// 因?yàn)檎{(diào)用對(duì)象方法是動(dòng)態(tài)綁定悠垛,動(dòng)態(tài)檢測(cè)對(duì)象的真實(shí)類型
// 然后就會(huì)去 `Dog` 里面找 `run` 方法,還是運(yùn)行成功
// 這樣寫不好逆航,可以強(qiáng)制轉(zhuǎn)換鼎文,將 `a` 轉(zhuǎn)換為 `Dog *` 類型的變量
Dog *dd = (Dog *)a;
[dd run];
Dog *d = [Dog new];
[d run];
return 0;
}