一、继承
继承是类中的一个重要的特性,他的出现使得我们没必要别写重复的代码,可重用性很高。
参考其他文献:
成员访问类型:1、private:私有成员,不能被外部函数访问(使用),也不能被子类继承;
2、protected:保护成员,不能被外部函数访问,可以被子类继承;
3、public:公有成员,可以被外部函数访问,也可以被子类继承。
OC中,所有的方法(消息),都是公有的。
子类可以从父类继承方法,但是有时候父类的方法不适合子类,子类就可以写一个自己的同名方法,覆盖掉父类的同名方法,叫做重写。
举例如下:
//父类声明文件
#import
@interface Father : NSObject
-(void)speak;
@end
//父类实现文件
#import "Father.h"
@implementation Father
-(void)speak{
NSLog(@"I am Father!");
return 0;
@end
子类:
//子类声明文件
#import "Father.h"
@interface Son : Father
@end
//子类实现文件
#import "Son.h"
@implementation Son
-(void)speak{
NSLog(@"I am son!");
}
@end
当重写父类方法后子类中self与super的调用就不一样了,self调用的是子类方法,而super调用的则是父类方法。
继承的使用场合:
1、当两个类拥有相同属性和方法时,可以讲相同的东西抽取到一个父类中;
2、当A类完全拥有B类的部分属性和方法时,可以考虑B类继承A类。
继承有两缺点:
(1)当层级越来越多时,假如每个层级都有实例变量,那么最下层的子类继承的实例变量会超级多,沉重;
(2)当消息传递自子类往上时,层级越多,效率越低下。
因此出现了组合,当继承不符合逻辑时考虑用组合,继承的关系是“A is B”,组合的关系是“A has B”。
二、多态
举个例子,创建Pc父类与
LenovePc和DellPc两个子类。
Pc.h
#import
@interface Pc : NSObject
- (void) power;
@end
#import "Pc.h"
@implementation Pc
- (void)power{
NSLog(@"PC power on!");
}
@end
LenovePc.h
#import "Pc.h"
//修改父类的行为
@interface LenovePc : Pc
- (void)power;
@end
LenovePc.m
#import "LenovePc.h"
@implementation LenovePc
- (void)power{
NSLog(@"LenovePc power on!");
}
@end
DellPc.h
#import "Pc.h"
//修改父类的打印行为
@interface DellPc : Pc
- (void)power;
@end
DellPc.m
#import "DellPc.h"
@implementation DellPc
- (void)power{
NSLog(@"DellPc power on!");
}
@end
在创建一个Person类用来操作Pc
Person.h
#import
@interface Person : NSObject
// - (void) powerWithLenove:(LenovePc *)lenovePc;
// - (void) powerWithDell:(DellPc *)dellPc;
- (void) doPower:(Pc *)pc;
@end
Person.m
#import "Person.h"
@implementation Person
/*
- (void) powerWithLenove:(LenovePc *)lenovePc{
[lenovePc power];
}
- (void) powerWithDell:(DellPc *)dellPc{
[dellPc power];
}
*/
- (void) doPower:(Pc *)pc{
[pc power];
}
@end
主函数
main.m
#import
#import "Person.h"
#import "LenovePc.h"
#import "DellPc.h"
int main(int argc, const charchar * argv[]) {
Person *person =[Person new];
LevoerPc *lenove = [LevoerPc new];
DellPc *dell = [DellPc new];
//多态的定义
/*
Pc *p1 = [LevoerPc new];
Pc *p2 = [DellPc new];
[person doPower:p1];
[person doPower:p2];
*/
int cmd;
do{
scanf("%d",&cmd);
if(cmd == 1){
// [person powerWithLenove:(LenovePc *)lenove]
[person doPower:lenove];
}else if(cmd == 2){
// [person powerWithDell:(DellPc *)dell]
[person doPrint:dell];
}
}while (1);
}
return 0;
}
如果我们不用多态机制实现的话(Person.h中注释的代码部分),我们就要给两种Pc单独定义操作的方法,在main.m中也需要分别调用这两种方法(mai.m中的27、30行):
[person powerWithLenove:(LenovePc *)lenove][person powerWithDell:(DellPc *)dell]
而使用多态后我们可以在Person中定义一个方法就足够了
-
(void)doPower:(Pc*)pc
这个方法的参数类型是父类的类型,这就是多态,定义类型为父类类型,实际类型为调用对象的实际类型。
调用方法:
Pc *p1 = [LevoerPc new];
Pc *p2 = [DellPc new];
[person doPower:p1];
[person doPower:p2];
person对象调用doPower方法,传递进去的实参看起来是Pc类型,但当实参调用power方法时会动态监测调用者的真实类型,即相应的LenovePc与DellPc类型,因此会调用子类的方法。