学过面向对象语言的小伙伴都知道,面向对象的语言(Java,C#,OC)都有三大特性:封装、继承、多态。
所谓封装,在OC中就是把变量和方法封装到一个类中;继承就是如果一个子类继承一个父类,那么子类就可以直接用父类的变量和方法,大大减少了代码的书写量并且提高了代码的可维护性(只要在父类中修改其中的变量和方法,子类继承过来的变量和方法也会随着改变,必须要一一修改);多态,从字面上理解就是多种形态,但仅仅知道这么多,怎么好意思说自己是学过面向对象的呢!
下面本人就板门弄斧的谈谈自己对多态的理解:
首先从多态的定义来说:
- 用一个父类的指针指向子类的对象,在函数(方法)调用的时候可以调用到正确版本的函数(方法)。
使用多态的条件:
1.子类必须重写父类的方法
2.父类指针指向子类对象
多态的应用场景:
- 用一个父类的指针指向子类的对象
****主函数****
#import <Foundation/Foundation.h>
//导入头文件
#import "Osier.h"
#import "PineTree.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
//父类的指针指向子类的对象
Tree *t1 = [[Osier alloc] init];
[t1 grow];
Tree *t2 = [[PineTree alloc] init];
[t2 grow];
}
return 0;
}
输出结果为:
柳树在春天发芽
松树四季常青
****父类(Tree)的文件****
//.h声明文件
#import <Foundation/Foundation.h>
@interface Tree : NSObject
@property NSString *name;
@property int age;
-(void)grow;
@end
//.m实现文件
#import "Tree.h"
@implementation Tree
-(void)grow
{
NSLog(@"树木生长");
}
@end
****子类(Osier)文件****
//.h声明文件
#import "Tree.h"
//柳树继承树这个类
@interface Osier : Tree
//重写父类grow方法
-(void)grow;
@end
//.m实现文件
#import "Osier.h"
@implementation Osier
-(void)grow
{
NSLog(@"柳树在春天发芽");
}
@end
****子类(PineTree)文件****
//.h声明文件
#import "Tree.h"
//松树继承树类
@interface PineTree : Tree
//重写父类的grow方法
-(void)grow;
@end
//.m实现文件
#import "PineTree.h"
@implementation PineTree
-(void)grow
{
NSLog(@"松树四季常青");
}
@end
-
用一个父类的指针当函数参数,用这个指针可以接受任何它的子类对象包括它自己。
****其他文件不变,只在主函数中改变,代码如下****
//其他文件不变,只在主函数中改变
#import <Foundation/Foundation.h>
#import "Osier.h"
#import "PineTree.h"
//定义一个函数,用父类指针作形参
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;
}
//输出结果为:
树木生长
柳树在春天发芽
松树四季常青
- 在复合类中,尽量引用高层次的类(父类)的指针当作复合类的成员变量,这样就可以通过它(父类的指针)创建出它所对应的任何子类对象包括它自己。
****定义一个复合类Person****
//定义一个复合类Person
#import <Foundation/Foundation.h>
//前向导入
@class Tree;
@class Osier;
@class PineTree;
//定义一个万能的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实现文件
#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
**** 主函数****
#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;
}
//输出结果:
name = 小明, age = 15
松树四季常青
总结:
多态的优点是提高程序的可扩展性
最后,如果有错误,请大牛们指点!本文仅供参考。