我們常說,OC語言中的三大特征是封裝、繼承和多態,這三大特點本質來說就是可以讓我們的代碼“活”起來,不再是牽一發動全身類型的代碼,讓我們開發者可以在改變、增添功能時,不再需要去基類去調整我們的代碼,只需要書寫好新的子類即可。
隱藏內部實現,穩定外部接口
使用起來更加簡單
變量更加安全
可以隱藏內部實現
開發速度更加快捷
類來封裝了屬性和方法
方法封裝了實現的代碼
NSString *_name; NSInteger age; NSString *_homeAddress;
@property(nonatomic,strong)NSString *name; @property (nonatomic,assign)NSInteger age; @property (nonatomic,strong)NSString *homeAddress;
-(void)hellWorld;
NSString *name=@"Jack"; NSInteger age= 25; NSString *homeAddress =@"G2"; NSLog(@"Student 's name is %@,%ld years old,living in %@",name,age,homeAddress); Student *stu=[[Student alloc]init]; [stu hellWorld]; // [stu hiGuys];
#import//在OC中,幾乎所有的類都繼承於NSObject @interface Student : NSObject { //使用類來封裝成員變量 // NSString *_name; // NSInteger age; // NSString *_homeAddress; } //使用property來封裝成員變量,實現變量安全 @property(nonatomic,strong)NSString *name; @property (nonatomic,assign)NSInteger age; @property (nonatomic,strong)NSString *homeAddress; //使用類來封裝功能代碼 -(void)hellWorld; @end
//重寫init方法
-(id)init{
if(self=[super init]){
_name=@”Jack”;
_age=25;
_homeAddress=@”G2”;
}
return self;
}
-(void)hellWorld{
NSLog(@”helloWorld”);
//打印哪個類裡面的哪個方法
NSLog(@”%s”,func);
NSLog(@”%s”,FUNCTION);
[self hiGuys];
}
//私有方法:@interface中沒有相關聲明的方法,可以把他們看作私有方法,僅在類的實現文件中使用
-(void)hiGuys{
NSLog(@”我是私有方法”);
NSLog(@”%s”,FUNCTION);
}
繼承是避免冗余,提高代碼的可重用性和可維護性的有效手段
直接父類 間接父類
子類和父類都需要滿足 is-a關系,才存在繼承
繼承概念下的is-a 關系是個單向的關系
子類具有父類的屬性和行為,以及自身特殊的屬性和行為
把這些類的父類設置為:Father
.h文件:
@interface Father : NSObject @property (nonatomic,strong)NSString *name; @property (nonatomic,assign)NSInteger age; @property (nonatomic,strong)NSString *hobby; -(void)sayHello; -(void)charge; @end
.m文件:
@implementation Father -(void)sayHello{ NSLog(@"Hello everybody,my name is %@",self.name); } -(void)charge{ NSLog(@"老子有錢,你隨便刷"); } @end
Son:
.h文件:
@interface Son : Father @property (nonatomic,strong)NSString *homeAddress; -(void)race; @end
.m文件:
@implementation Son //重寫父類中的charge的方法 -(void)charge{ [super charge]; NSLog(@"拿老爸的卡出來刷一下"); } -(void)sayHello{ NSLog(@"home address is %@",self.homeAddress); } -(void)race{ NSLog(@"race"); } @end
SonA .m文件:
@implementation SonA -(void)sayHello{ [super sayHello]; NSLog(@"I am SonA"); } @end
SonB .m文件:
@implementation SonB -(void)sayHello{ [super sayHello]; NSLog(@"I am SonB"); } @end
Father *father=[[Father alloc]init]; father.name=@"Jack"; [father sayHello]; [father charge]; NotInheritedSon *aSon=[[NotInheritedSon alloc]init]; aSon.name=@"xxx"; [aSon sayHello]; [aSon charge]; Son *son =[[Son alloc]init]; [son charge]; son.homeAddress=@"GZ"; [son sayHello]; [son race];
大家會注意到上面的代碼裡面還有SonA和SonB沒用在主函數吧?這就是我們接下來講的多態的一個例子。
多態就是對於不同對象相應同一個方法時做出的不同反應,它是建立在繼承的基礎上面。
1.繼承與同一個父類的子類,他們本身具有自己的特征
2.繼承與同一個父類的子類,在執行同一命令的時候,可以具有不同的效果
SonA *sonA=[[SonA alloc]init]; sonA.name=@"sonA"; [sonA sayHello]; SonB *sonB=[[SonB alloc]init]; sonB.name=@"sonB"; [sonB sayHello];
這就是輸出的結果,我們可以看到在子類通過重寫父類的方法,可以達到不同子類調用同一個父類的方法可以數出不同的結果,
當然如果要重寫父類的時候,還有帶上父類的效果的話,就要使用 [super 父類中的的方法名]來讓子類重寫的時候保持原來的父類方法的輸出。
允許多個類中定義同一消息借口
可以定義一個通用的調用方法,以簡化調用
2.把不同的子類對象都當做父類來看
可以屏蔽不同子類對象之間的差異,寫出通用的代碼
做出通用的編程,以適應需求的不斷變化。
例子:
按照下圖建立以下類:(讓Dog Cat類繼承於Animal類,其他都繼承於NSObject)
主函數如下:
id animal=nil;
//由於id類型的通用性質,我們可以將創建好的任意對象賦值給animal
animal=[[Cat alloc]init];
[animal eat];
animal=[[Dog alloc]init];
[animal eat];
Animal *animalB=nil;
animalB =[Cat new];
[animalB eat];
animalB =[Dog new];
[animalB eat];
Animal類如下:
@interface Animal : NSObject
-(void)eat;
@end
@implementation Animal
-(void)eat{
NSLog(@"動物吃東西");
}
@end
Cat類如下:
@implementation Cat
-(void)eat{
[super eat];
NSLog(@"Cat eats fish");
}
@end
Dog類如下:
@implementation Dog
-(void)eat{
[super eat];
NSLog(@"Dog eats bone");
}
@end
開閉原則和裡氏替換原則
開閉原則:
對擴展開放,對修改關閉
裡氏替換原則:
任何基類可以出現的地方,子類一定可以出現,
如果我們增加一個person類,由於寫人喂養XXX動物,這樣是不是比如我們喂養上述的動物,就要寫[p feedCat:cat]和 [p feedDog:dog]這兩個方法,那我們如果還有增加十幾只動物呢?那樣我們寫代碼就會有很大的冗余度;所以我們要遵循開閉原則和裡氏替換原則
主函數main.m:
Cat *cat=[Cat new];
Dog *dog=[Dog new];
Person *p=[[Person alloc]init];
//[p feedCat:cat];
// [p feedDog:dog];
[p feedAnimal:cat];
Person *p=[[Person alloc]init];
[p feedAnimal:cat];
Person.h文件:
#import
#import "Cat.h"
#import "Dog.h"
#import "Animal.h"
@interface Person : NSObject
-(void)feedCat:(Cat* )cat;
-(void)feedDog:(Dog* )dog;
-(void)feedAnimal:(Animal * )animal;
@end
Person.m文件:
@implementation Person
-(void)feedCat:(Cat* )cat{
NSLog(@"人喂貓");
[cat eat];
}
-(void)feedDog:(Dog* )dog{
NSLog(@"人喂狗");
[dog eat];
}
-(void)feedAnimal:(Animal * )animal{
if([animal isMemberOfClass:[Cat class]]){
NSLog(@"人喂貓");
[animal eat];
}
if([animal isMemberOfClass:[Dog class]]){
NSLog(@"人喂狗");
[animal eat];
}
}
@end