學(xué)習(xí)目標(biāo)
1.【了解】異常處理
2.【掌握】類(lèi)方法
3.【掌握】NSString類(lèi)
4.【掌握】匿名對(duì)象
5.【掌握】封裝實(shí)例變量
6.【掌握】對(duì)象之間的關(guān)系
一、異常處理
什么是異常?
代碼完全符合語(yǔ)法規(guī)范,可以編譯、鏈接、執(zhí)行,但是在程序運(yùn)行的時(shí)候,當(dāng)程序處于某種特定情況下的時(shí)候,程序運(yùn)行就會(huì)出錯(cuò),像這樣的情況就叫做程序發(fā)生了異常。一旦發(fā)生異常,程序會(huì)立即奔潰。為了避免程序在發(fā)生異常的時(shí)候奔潰,OC提供了@try @catch異常處理。
異常處理語(yǔ)法:
@try {
//可能發(fā)生異常的代碼
}
@catch (NSException *指針名) {
//發(fā)生異常后執(zhí)行的代碼
}
@finally {
//無(wú)論有沒(méi)有發(fā)生異常,都會(huì)執(zhí)行的代碼
}
執(zhí)行步驟:
第一種情況:先執(zhí)行@try中的代碼,如果這里面的代碼發(fā)生了異常,系統(tǒng)就會(huì)把異常信息存儲(chǔ)到@catch中的指針變量,然后執(zhí)行@catch中的代碼。@catch中的代碼執(zhí)行完畢后,還會(huì)執(zhí)行@finally中的代碼(@finally是可選的)。
第二種情況:先執(zhí)行@try中的代碼,如果@try中的代碼不發(fā)生異常,@catch中的代碼不會(huì)執(zhí)行。但還是會(huì)執(zhí)行@finally中的代碼(@finally是可選的)。所以,@catch中的代碼只有在@try中的代碼發(fā)生異常的時(shí)候才會(huì)執(zhí)行。
注意:
1.@try-@catch只能處理OC中的異常(跟類(lèi)和對(duì)象有關(guān)的)。
2.寫(xiě)代碼過(guò)程中盡力使用if來(lái)判斷,避免異常。
3.@finally不是必須寫(xiě)的語(yǔ)句,可以沒(méi)有@finally。
二、類(lèi)方法
OC中的方法分為兩種,對(duì)象方法(實(shí)例方法)和類(lèi)方法(靜態(tài)方法)。
對(duì)象方法:依賴(lài)于對(duì)象,對(duì)象方法必須創(chuàng)建對(duì)象,通過(guò)對(duì)象名來(lái)調(diào)用。
類(lèi)方法:不依賴(lài)與對(duì)象,類(lèi)方法不需要?jiǎng)?chuàng)建對(duì)象,通過(guò)類(lèi)名來(lái)調(diào)用。
聲明語(yǔ)法:+ (返回值類(lèi)型)方法名;
//聲明類(lèi)方法
@interface Person : NSObject
+ (void)test;
@end
//實(shí)現(xiàn)類(lèi)方法
@implementation Person
+ (void)test{
NSLog(@"this is a class method!");
}
@end
//主函數(shù)里調(diào)用類(lèi)方法
[Person test];
注意:
1.對(duì)象方法和類(lèi)方法的方法名可以同名,兩個(gè)方法互不影響。
2.類(lèi)方法調(diào)用不需要?jiǎng)?chuàng)建對(duì)象,從效率上而言會(huì)更快一些。
3.對(duì)象方法只能通過(guò)對(duì)象名來(lái)調(diào)用,類(lèi)方法只能通過(guò)類(lèi)名來(lái)調(diào)用。
4.對(duì)象方法中可以直接訪問(wèn)實(shí)例變量和類(lèi)方法,類(lèi)方法中不能直接訪問(wèn)實(shí)例變量和對(duì)象方法。
5.如果方法不需要訪問(wèn)對(duì)象的實(shí)例變量的時(shí)候,我們可以將其定義為類(lèi)方法,提高效率。
類(lèi)方法的規(guī)范
提供一個(gè)和類(lèi)同名的類(lèi)方法來(lái)創(chuàng)建一個(gè)對(duì)象。比如:
+ (Person *)person;//聲明類(lèi)方法
//實(shí)現(xiàn)類(lèi)方法
+ (Person *)person{
Person *person = [Person new];//創(chuàng)建對(duì)象person
return person;//返回對(duì)象person
}
提供一個(gè)類(lèi)方法創(chuàng)建對(duì)象,并讓調(diào)用者可以初始化新創(chuàng)建對(duì)象的實(shí)例變量的值。比如:
+ (Person *)personWithName:(NSString *)name;//聲明類(lèi)方法
//實(shí)現(xiàn)類(lèi)方法
+ (Person *)personWithName:(NSString *)name{
Person *person = [Person new];//創(chuàng)建對(duì)象person
person -> _name = name;//將調(diào)用者傳遞進(jìn)來(lái)的參數(shù)賦值給person對(duì)象的實(shí)例變量
return person;//返回對(duì)象person
}
三、NSString類(lèi)
OC中提供了一個(gè)字符串類(lèi)NSString,以對(duì)象的形式存儲(chǔ)字符串。
NSString類(lèi)的常用方法
//stringWithCString:將C語(yǔ)言字符串轉(zhuǎn)化為OC字符串。
NSString *str = [NSString stringWithCString:"C字符串"];
//stringWithFormat:格式化字符串,也可以做多個(gè)變量、字符串的拼接。
for(int i = 1;i <= 1000;i++){
NSString *str = [NSString stringWithFormat:@"d",i];
NSLog(@"%@",str);
}
//length計(jì)算字符串長(zhǎng)度,是計(jì)算字符個(gè)數(shù),一個(gè)中文字也是1個(gè)長(zhǎng)度。
NSString *str = @"字符串a(chǎn)bcd";
NSUInteger length = [str length];//這里是長(zhǎng)度為7
//characterAtIndex:獲取指定位置的字符,位置從0開(kāi)始遞增。
NSString *str = @"字符串a(chǎn)bcd";
unichar ch = [str characterAtIndex:3];//從0開(kāi)始計(jì)算
NSLog(@"ch = %C",ch); //%C OC里新增的格式控符,可以輸出單個(gè)中文
//isEqualToString:比較兩個(gè)字符串是否相同。
NSString *str = @"字符串a(chǎn)bcd";
NSString *str1 = @"字符串a(chǎn)bcd";
BOOL res = [str isEqualToString:str1];
//compare:比較兩個(gè)字符串的大小(ASCII)
NSString *s1 = @"China";
NSString *s2 = @"Japan";
int res = [s1 compare:s2];
NSLog(@"res = %i",res);//s1 < s2則返回1? s1 > s2 返回-1 相等返回0
四、匿名對(duì)象
實(shí)例化一個(gè)對(duì)象的時(shí)候,沒(méi)有用任何指針指向這個(gè)對(duì)象,這個(gè)對(duì)象就是匿名對(duì)象。并且匿名對(duì)象只能調(diào)用一次,所以如果你只是為了調(diào)用某一個(gè)對(duì)象的對(duì)象方法,就可以使用匿名對(duì)象。比如:
//Person.h文件
#import
@interface Person : NSObject
{
NSString *_name;
}
- (void)sayHi;
@end
//Person.m文件
#import "Person.h"
@implementation Person
- (void)sayHi{
NSLog(@"這是對(duì)象方法");
}
@end
//main.m文件
#import
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//給匿名對(duì)象的實(shí)例變量賦值,不過(guò)匿名對(duì)象只能訪問(wèn)一次,賦值后就不能再使用了
[Person new] -> name = @"jack";
//調(diào)用匿名對(duì)象的對(duì)象方法,調(diào)用完了就不再用這個(gè)對(duì)象了
[[Person new] sayHi];
}
return 0;
}
五、封裝實(shí)例變量
一個(gè)類(lèi)之中有多個(gè)屬性、方法,把這些成員封裝在一個(gè)類(lèi)中,把這個(gè)類(lèi)當(dāng)做一個(gè)整體來(lái)使用。
封裝的好處:便于管理代碼的維護(hù),以類(lèi)為單位來(lái)管理他們。屏蔽內(nèi)部的實(shí)現(xiàn),對(duì)于外部而言只是一個(gè)對(duì)象。
為對(duì)象的屬性賦值的時(shí)候,只要賦值的數(shù)據(jù)的類(lèi)型和屬性的類(lèi)型一致就可以了。但是,這樣的賦值往往都不能隨意賦值。比如人的年齡為int類(lèi)型,我們賦值-10語(yǔ)法也不會(huì)報(bào)錯(cuò)。但這種賦值不符合實(shí)際情況,所以我們要為屬性賦值范圍加以限定。
首先,實(shí)例變量一定不能被@public修飾,因?yàn)橐坏┍籃public修飾,就能在外界通過(guò)對(duì)象名來(lái)訪問(wèn)這個(gè)實(shí)例變量,隨意修改實(shí)例變量的值。然后給實(shí)例變量提供兩種方法來(lái)供外界為實(shí)例變量賦值和訪問(wèn),也就是setter和getter方法。只有g(shù)etter方法沒(méi)有setter方法叫只讀封裝,只有setter方法沒(méi)有g(shù)etter方法叫只寫(xiě)封裝。
為類(lèi)提供一種專(zhuān)門(mén)為實(shí)例變量賦值的方法 setter
1.這個(gè)方法一定是一個(gè)對(duì)象方法,因?yàn)橹挥袑?duì)象方法才能直接訪問(wèn)實(shí)例變量。
2.這個(gè)方法一定沒(méi)有返回值,為實(shí)例變量賦值不需要返回值。
3.這個(gè)方法一定是有參數(shù)的,為實(shí)例變量賦值一定需要傳入一個(gè)和實(shí)例變量類(lèi)型相同的參數(shù)。
4.這個(gè)方法的方法名以set開(kāi)頭,后面跟實(shí)例變量名去掉下劃線,并首字母大寫(xiě)。
為類(lèi)提供一種專(zhuān)門(mén)訪問(wèn)實(shí)例變量的值的方法 getter
1.這個(gè)方法一定是一個(gè)對(duì)象方法,因?yàn)橹挥袑?duì)象方法才能直接訪問(wèn)實(shí)例變量。
2.這個(gè)方法一定有返回值,供外界訪問(wèn)實(shí)例變量,必須要返回給調(diào)用者實(shí)例變量的值。
3.這個(gè)方法一定沒(méi)有參數(shù),訪問(wèn)實(shí)例變量的值不需要傳入任何參數(shù)。
4.這個(gè)方法的方法名就是去掉下劃線的實(shí)例變量的名字。
//Person.h文件
#import
@interface Person : NSObject
{
//不要給實(shí)例變量@public修飾
int _age;
}
//setter聲明
- (void)setAge:(int)age;
//getter聲明
- (int)age;
@end
//Person.m文件
#import "Person.h"
@implementation Person
//setter實(shí)現(xiàn)
- (void)setAge:(int)age{
//傳入的年齡在 0 - 120之間才能賦值,否則輸出提示
if(age > 0 && age < 120){
_age = age;
}else{
NSLog(@"年齡不符合");
}
}
//getter實(shí)現(xiàn)
- (int)age{
return _age;
}
@end
//main.m文件
#import
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//實(shí)例化一個(gè)對(duì)象p
Person *p = [Person new];
//調(diào)用p對(duì)象setAge方法為對(duì)象的實(shí)例變量賦值
[p setAge:200];//因?yàn)椴环弦?guī)范,會(huì)打印出 年齡不符合
//輸出p對(duì)象的實(shí)例變量age的值
NSLog(@"age = %i",[p age]);//輸出 age = 0
}
return 0;
}
注意:
1.setter和getter方法的命名必須符合規(guī)范。
2.實(shí)例變量無(wú)論如何都不能用@public修飾,不然就不符合封裝的理念。
3.只要實(shí)例變量要被外界訪問(wèn),都應(yīng)該為他封裝一個(gè)setter和getter方法。
六、對(duì)象之間的關(guān)系
組合關(guān)系
一個(gè)類(lèi)是由多個(gè)對(duì)象組合而成的(多個(gè)對(duì)象都是同一個(gè)類(lèi)的實(shí)例變量),那么他們之間的關(guān)系就叫組合關(guān)系。
依賴(lài)關(guān)系
一個(gè)方法的參數(shù)是另一個(gè)對(duì)象(依賴(lài)參數(shù)那個(gè)對(duì)象,沒(méi)有了參數(shù)就無(wú)法整了),那么他們之間的關(guān)系就是依賴(lài)關(guān)系。
關(guān)聯(lián)關(guān)系
當(dāng)一個(gè)對(duì)象擁有另外一個(gè)對(duì)象的時(shí)候(一個(gè)對(duì)象是另一個(gè)對(duì)象的實(shí)例變量,但是他們并不是組合關(guān)系),那么他們之間的關(guān)系就是關(guān)聯(lián)關(guān)系。
面向?qū)ο笤O(shè)計(jì)中:
耦合度? 當(dāng)修改一個(gè)對(duì)象的時(shí)候,對(duì)另外一個(gè)對(duì)象的影響程度
低耦合? 當(dāng)修改一個(gè)對(duì)象的對(duì)其他對(duì)象影響比較小
高內(nèi)聚? 一個(gè)對(duì)象僅僅做自己相關(guān)的事情
面向?qū)ο笤O(shè)計(jì)原則是高內(nèi)聚、低耦合,單一職責(zé)原則。