继承的基本概念:ide
现实生活中的继承:工具
人类是一个基类(也称作父类),一般状况下全部人类所共同具有的特性,若有手有脚能吃能喝性能
按照生活常规,咱们继续给人类来细分的时候,咱们能够分为学生类 工人类等,学生类和工人类一样具有手 脚 吃 喝等特性,而这些特性是全部人类所共有的,那么就可让学生或工人类继承人类,这样当创建学生类和工人类的时候咱们无需再定义人类中已经有的成员和方法,而只须要描述学生类和工人类所特有的特性便可。学习
学生类和工人类的特性是由在人类原有特性基础上增长而来的,那么学生类和工人类就是人类的派生类(也称作子类)。以此类推,层层递增, 这种子类得到父类特性的概念就是继承spa
OC中的继承关系code
继承是代码重用的重要方式之一对象
学生类声明文件.h:blog
#import <Foundation/Foundation.h> @interface Student : NSObject { // 姓名 NSString * _name; // 年龄 int _age; // 学号 int _studengNO; // 身份 NSString * _identity; } - (void) setName:(NSString *) name; - (NSString *) name; - (void) setAge: (int) age; - (int) age; - (void) setStudentNO: (int) studentNO; - (int) studentNO; - (void) setIdentity: (NSString *) identity; - (NSString *) identity; // 吃 - (void) eat; // 学习 - (void) study; @end
学生类实现文件.m:继承
#import "Student.h" @implementation Student - (void)setName:(NSString *)name{ _name = name; } - (NSString *)name{ return _name; } - (void)setAge:(int)age{ _age = age; } - (int)age{ return _age; } - (void)setStudentNO:(int)studentNO{ _studengNO = studentNO; } - (int)studentNO{ return _studengNO; } - (void)setIdentity:(NSString *)identity{ _identity = identity; } - (NSString *) identity{ return _identity; } // 吃 - (void)eat{ NSLog(@"吃东西"); } // 学习 - (void)study{ NSLog(@"学习"); } @end
工人类声明文件.h:接口
#import <Foundation/Foundation.h> @interface Worker : NSObject { // 姓名 NSString * _name; // 年龄 int _age; // 工号 int _workNO; // 身份 NSString * _identity; } - (void) setName: (NSString *) name; - (NSString *) name; - (void) setAge: (int) age; - (int) age; - (void) setWorkNO: (int) workNO; - (int) workNO; - (void) setIdentity: (NSString *) identity; - (NSString *) identity; // 吃 - (void) eat; // 学习 - (void) study; // 工做 - (void) work; @end
工人类实现文件:
#import "Worker.h" @implementation Worker - (void)setName:(NSString *)name{ _name = name; } - (NSString *)name{ return _name; } - (void)setAge:(int)age{ _age = age; } - (int)age{ return _age; } - (void)setWorkNO:(int)workNO{ _workNO = workNO; } - (int)workNO{ return _workNO; } - (void)setIdentity:(NSString *)identity{ _identity = identity; } - (NSString *) identity{ return _identity; } // 吃 - (void)eat{ NSLog(@"吃东西"); } // 学习 - (void)study{ NSLog(@"学习"); } // 工做 - (void)work{ NSLog(@"上班了 干活"); } @end
比较一下上面的代码 看看有多少是重复的:
声明文件中重复部分:
属性:
// 姓名 NSString * _name; // 年龄 int _age; // 身份 NSString * _identity;
行为:
- (void) setName:(NSString *) name; - (NSString *) name; - (void) setAge: (int) age; - (int) age; - (void) setIdentity: (NSString *) identity; - (NSString *) identity; // 吃 - (void) eat; // 学习 - (void) study;
实现文件中重复部分:
- (void)setName:(NSString *)name{ _name = name; } - (NSString *)name{ return _name; } - (void)setAge:(int)age{ _age = age; } - (int)age{ return _age; } - (void)setIdentity:(NSString *)identity{ _identity = identity; } - (NSString *) identity{ return _identity; } // 吃 - (void)eat{ NSLog(@"吃东西"); } // 学习 - (void)study{ NSLog(@"学习"); }
获得的结果是:
学生类中就一个学号在工人类中没有
工人类中就一个工号和一个工做的行为在学生类中没有
其他部分都是重复代码
若是还要添加几个其余类: 如学前期的幼儿类 退休后的老人类等等 那么上面那些重复的代码还得重复好几遍 复制粘贴都感受累有木有
如今咱们来添加一个Person类 人类中定义属性有 姓名 (name) 年龄(age) 身份(identity) 行为有 吃(eat) 学习(study)
使用继承关系后再来看看代码:
Person类声明文件:
#import <Foundation/Foundation.h> @interface Person : NSObject { // 姓名 NSString * _name; // 年龄 int _age; // 身份 NSString * _identity; } - (void) setName:(NSString *) name; - (NSString *) name; - (void) setAge: (int) age; - (int) age; - (void) setIdentity: (NSString *) identity; - (NSString *) identity; // 吃 - (void) eat; // 学习 - (void) study; @end
Person类实现文件:
#import "Person.h" @implementation Person - (void)setName:(NSString *)name{ _name = name; } - (NSString *)name{ return _name; } - (void)setAge:(int)age{ _age = age; } - (int)age{ return _age; } - (void)setIdentity:(NSString *)identity{ _identity = identity; } - (NSString *) identity{ return _identity; } // 吃 - (void)eat{ NSLog(@"吃东西"); } // 学习 - (void)study{ NSLog(@"学习"); } @end
学生类声明文件:
#import <Foundation/Foundation.h> #import "Person.h" @interface Student : Person { // 学号 int _studengNO; } - (void) setStudentNO: (int) studentNO; - (int) studentNO; @end
学生类实现文件:
#import "Student.h" @implementation Student - (void)setStudentNO:(int)studentNO{ _studengNO = studentNO; } - (int)studentNO{ return _studengNO; } @end
工人类的声明文件:
#import <Foundation/Foundation.h> #import "Person.h" @interface Worker : Person { // 工号 int _workNO; } - (void) setWorkNO: (int) workNO; - (int) workNO; // 工做 - (void) work; @end
工人类的实现文件:
#import "Worker.h" @implementation Worker - (void)setWorkNO:(int)workNO{ _workNO = workNO; } - (int)workNO{ return _workNO; } // 工做 - (void)work{ NSLog(@"上班了 干活"); } @end
好了, 如今再来看看代码: 咱们的代码中多了一个Person类的声明和实现文件 在这个类中声明定义的就是咱们以前学生类和工人类中重复的那一部分.
"B类继承A类,那么B类将拥有A类的全部属性和方法" 就是说若是 咱们让学生类和工人类都继承自Person类 , 那么就算咱们在学生类中和工做类中都没有声明那些姓名 年龄 吃 学习之类的属性和方法, 这两个类也能从Person类中获得这些行为属性. 而在学生类中只须要声明学生类特有的学号属性, 工人类中只须要声明工人类特有的工号,工做这种特有的行为属性便可, 这样子在学生类和工人类中得代码看起来简洁了不少, 并且之后若是咱们须要再添加什么婴儿类 老人类, 也只须要在相关类中添加他们特有的行为属性就好了.
在这个例子里, Person类就是父类 学生类和工人类就是Person类的子类, 须要注意的是OC也是单继承的, 毕竟咱都只有一个父亲是吧, (呃 那个 干爹不算) , 在父类中定义的全部行为属性, 子类都能继承过去, 而在子类中还能够添加他特有的行为属性, 也就是说我爸有的 我都有, 我有的, 我爸不必定有(例如: 我会打Dota 我爸不会 ).
当咱们发现两个类中有定义不少重复的行为属性的时候, 即可以把这些重复的部分都抽取出来当一个父类; 继承对代码的重用性和可扩展性 , 看上面例子体会一下吧
OC中继承的实现格式:
@interface 子类名称 : 父类名称 @end
记得导入父类头文件
继承:
当B类继承A类, 那么B类就拥有A类全部的属性和方法(类方法/对象方法)
优势:
提升代码的复用性
可让类与类之间产生关系, 正是由于继承让类与类之间产生了关系因此才有了多态
缺点: 增长了代码之间的耦合性
注意:
不要觉得继承能够提升代码的复用性, 之后但凡发现多个类当中有重复代码就抽取一个父类
只要知足必定的条件咱们才能使用继承
条件: XXXX 是 XXX / 某某某 is a 某某某 (继承是 '是' 的关系 接口(协议) 是 '有' 的关系)
方法的重写:
方法重写: 子类从父类继承了父类的方法(行为) 可是不想用父类的实现体 能够本身提供新的实现覆盖掉父类的实现
举例: 我爸会打人 我从我爸那也继承了打人的行为 我爸打人用拳头打 可是我感受用拳头打不爽 就能够用本身的方式去打 (如用板砖砸) 这样虽然都是打人的方法 可是我用板砖打覆盖了从我爸那继承来的用拳头打 这样方法名相同 可是方法的实现子类和父类不一样(子类的实现覆盖了父类的实现) 就是方法的重写
在上面例子中咱们来重写父类学习的方法:
Person类中得学习方法实现:
// 学习 - (void)study{ NSLog(@"学习"); }
工人类重写父类的学习方法:
// 学习 - (void)study{ NSLog(@"咱们在职人员经过上网来学习"); }
学生类重写父类的方法:
// 学习 - (void)study{ [super study]; NSLog(@"咱们学生都经过去上课来学习"); }
继承中方法调用的顺序:
一、在本身类中找
二、若是没有,去父类中找
三、若是父类中没有,就去父类的父类中
四、若是父类的父类也没有,就还往上找,直到找到基类(NSObject)
五、若是NSObject都没有就报错了
以上若是找到了就执行这个方法,就再也不日后查找了
继承的注意事项:
super关键字:
概念: super是个编译器的指令符号,只是告诉编译器在执行的时候,去调谁的方法
做用: 直接调用父类中的某个方法
super在对象方法中,那么就会调用父类的对象方法 super在类方法中,那么就会调用父类的类方法
使用场合: 子类重写父类的方法时想保留父类的一些行为