學(xué)過面向?qū)ο笳Z(yǔ)言的小伙伴都知道外永,面向?qū)ο蟮恼Z(yǔ)言(Java,C#拧咳,OC)都有三大特性:封裝伯顶、繼承、多態(tài)骆膝。
所謂封裝祭衩,在OC中就是把變量和方法封裝到一個(gè)類中;繼承就是如果一個(gè)子類繼承一個(gè)父類阅签,那么子類就可以直接用父類的變量和方法掐暮,大大減少了代碼的書寫量并且提高了代碼的可維護(hù)性(只要在父類中修改其中的變量和方法,子類繼承過來(lái)的變量和方法也會(huì)隨著改變愉择,必須要一一修改)劫乱;多態(tài),從字面上理解就是多種形態(tài)锥涕,但僅僅知道這么多衷戈,怎么好意思說(shuō)自己是學(xué)過面向?qū)ο蟮哪兀?/p>
下面本人就板門弄斧的談?wù)勛约簩?duì)多態(tài)的理解:
首先從多態(tài)的定義來(lái)說(shuō):
- 用一個(gè)父類的指針指向子類的對(duì)象,在函數(shù)(方法)調(diào)用的時(shí)候可以調(diào)用到正確版本的函數(shù)(方法)层坠。
使用多態(tài)的條件:
1.子類必須重寫父類的方法
2.父類指針指向子類對(duì)象
多態(tài)的應(yīng)用場(chǎng)景:
- 用一個(gè)父類的指針指向子類的對(duì)象
****主函數(shù)****
#import <Foundation/Foundation.h>
//導(dǎo)入頭文件
#import "Osier.h"
#import "PineTree.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//父類的指針指向子類的對(duì)象
Tree *t1 = [[Osier alloc] init];
[t1 grow];
Tree *t2 = [[PineTree alloc] init];
[t2 grow];
}
return 0;
}
輸出結(jié)果為:
柳樹在春天發(fā)芽
松樹四季常青
****父類(Tree)的文件****
//.h聲明文件
#import <Foundation/Foundation.h>
@interface Tree : NSObject
@property NSString *name;
@property int age;
-(void)grow;
@end
//.m實(shí)現(xiàn)文件
#import "Tree.h"
@implementation Tree
-(void)grow
{
NSLog(@"樹木生長(zhǎng)");
}
@end
****子類(Osier)文件****
//.h聲明文件
#import "Tree.h"
//柳樹繼承樹這個(gè)類
@interface Osier : Tree
//重寫父類grow方法
-(void)grow;
@end
//.m實(shí)現(xiàn)文件
#import "Osier.h"
@implementation Osier
-(void)grow
{
NSLog(@"柳樹在春天發(fā)芽");
}
@end
****子類(PineTree)文件****
//.h聲明文件
#import "Tree.h"
//松樹繼承樹類
@interface PineTree : Tree
//重寫父類的grow方法
-(void)grow;
@end
//.m實(shí)現(xiàn)文件
#import "PineTree.h"
@implementation PineTree
-(void)grow
{
NSLog(@"松樹四季常青");
}
@end
-
用一個(gè)父類的指針當(dāng)函數(shù)參數(shù)殖妇,用這個(gè)指針可以接受任何它的子類對(duì)象包括它自己。
****其他文件不變破花,只在主函數(shù)中改變谦趣,代碼如下****
//其他文件不變疲吸,只在主函數(shù)中改變
#import <Foundation/Foundation.h>
#import "Osier.h"
#import "PineTree.h"
//定義一個(gè)函數(shù),用父類指針作形參
void grow(Tree *t)
{
[t grow];
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
Tree *t0 = [[Tree alloc] init];
grow(t0);
Tree *t1 = [[Osier alloc] init];
grow(t1);
Tree *t2 = [[PineTree alloc] init];
grow(t2);
}
return 0;
}
//輸出結(jié)果為:
樹木生長(zhǎng)
柳樹在春天發(fā)芽
松樹四季常青
- 在復(fù)合類中前鹅,盡量引用高層次的類(父類)的指針當(dāng)作復(fù)合類的成員變量摘悴,這樣就可以通過它(父類的指針)創(chuàng)建出它所對(duì)應(yīng)的任何子類對(duì)象包括它自己。
****定義一個(gè)復(fù)合類Person****
//定義一個(gè)復(fù)合類Person
#import <Foundation/Foundation.h>
//前向?qū)?@class Tree;
@class Osier;
@class PineTree;
//定義一個(gè)萬(wàn)能的Person類
@interface Person : NSObject
@property(nonatomic, retain) NSString *name;
@property(nonatomic, assign) int age;
@property(nonatomic, retain) Tree *tree;
-(instancetype)initWithName:(NSString *)name andAge:(int)age;
@end
//Person .m實(shí)現(xiàn)文件
#import "Person.h"
#import "Tree.h"
#import "Osier.h"
#import "PineTree.h"
@implementation Person
-(instancetype)initWithName:(NSString *)name andAge:(int)age
{
if(self = [super init])
{
_name = name;
_age = age;
_tree = [[PineTree alloc] init];
}
return self;
}
-(NSString *)description
{
return [NSString stringWithFormat:@"name = %@, age = %i", _name, _age];
}
@end
**** 主函數(shù)****
#import <Foundation/Foundation.h>
#import "Osier.h"
#import "PineTree.h"
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc]initWithName:@"小明" andAge:15];
NSLog(@"%@", p);
[p.tree grow];
}
return 0;
}
//輸出結(jié)果:
name = 小明, age = 15
松樹四季常青
總結(jié):
多態(tài)的優(yōu)點(diǎn)是提高程序的可擴(kuò)展性
最后舰绘,如果有錯(cuò)誤蹂喻,請(qǐng)大牛們指點(diǎn)!本文僅供參考捂寿。