继承

继承是面向对象最显著的一个特性。继承是从已有的类中派生出新的类,新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

为什么有继承

假设现在有两个类,分别是教师类与学生类,定义如下: 1. #import 2. 3. @interface Teacher : NSObject { 4. 5. NSString *_name; 6. NSInteger _age; 7. float _height; 8. float _salary; 9. } 10. 11. @end

  1. #import <Foundation/Foundation.h>
    2.   3. @interface Student : NSObject {
    4.   5.     NSString *_name;
    6.     NSInteger _age;
    7.     float _height;
    8.     float _score;
    9. }
    10.   11. @end

不难看出,学生类与教师类都有姓名、年龄与身高。那么,可不可以想一个办法,把这些都有的成员提取(抽象)出来,作为一个类,然后让学生和教师都引入就行了呢?答案是,可以的,使用继承就行。

怎么继承

对于上面的问题,我们需要使用到继承。 1. 对于Student与Teacher两个类来说,首先要找到共有的部分(即姓名、年龄、身高); 2. 然后他们都是属于人类的; 3. 那么我们就可以抽象出一个人类,然后让Teacher与Student来继承它。

首先,人类的定义: 1. #import 2. 3. @interface Person : NSObject { 4. 5. NSString *_name; 6. NSInteger _age; 7. float _height; 8. } 9. 10. @end

然后,学生有自己独有的成员变量,叫做_score,写法如下: 1. #import 2. #import "Person.h" 3. 4. // 注意:继承关系变成了Student继承自Person 5. @interface Student : Person { 6. 7. float _score; 8. } 9. 10. @end

教师类也有独有的成员变量,叫做_salary,写法如下: 1. #import 2. #import "Person.h" 3. 4. // 注意:继承关系变成了Teacher继承自Person 5. @interface Teacher : Person { 6. 7. float _salary; 8. } 9. 10. @end

继承与方法

与上面使用继承的原因相同,对于人类来说,有自己的初始化方法,比如直接自定义init方法来初始化成员变量,Person类中的定义与实现如下: 1. #import 2. 3. @interface Person : NSObject { 4. 5. NSString *_name; 6. NSInteger _age; 7. float _height; 8. } 9. 10. - (instancetype)initWithName:(NSString *)name age:(NSInteger)age height:(float)height; 11. 12. @end

  1. #import "Person.h"
    2.   3. @implementation Person
    4.   5. - (instancetype)initWithName:(NSString *)name age:(NSInteger)age height:(float)height {
    6.   7.     self = [super init];
    8.   9.     if (self) {
    10.   11.         _name = name;
    12.         _age = age;
    13.         _height = height;
    14.     }
    15.   16.     return self;
    17. }
    18.   19. @end

同样,因为Student与Teacher继承自Person,所以他们也可以直接调用自定义init方法来进行对象的初始化。 1. #import 2. #import "Person.h" 3. #import "Student.h" 4. #import "Teacher.h" 5. 6. int main(int argc, const char * argv[]) { 7. @autoreleasepool { 8. // insert code here... 9. 10. Person *person = [[Person alloc] initWithName:@"A" age:0 height:10]; 11. Teacher *teacher = [[Teacher alloc] initWithName:@"B" age:3 height:12]; 12. Student *student = [[Student alloc] initWithName:@"C" age:5 height:16]; 13. } 14. return 0; 15. }

访问权限修饰符

权限修饰符是用来修饰实例变量的,用来控制实例变量的访问权限。 常用的访问权限修饰符有:@public,@protected,@private,区别如下: 修饰符名称 | 修饰后的变量作用域 | 其他说明
---|---|---
@public | 所有地方都能访问 | 少用,容易破坏封装性
@protected | 在本类中与子类中可以访问 | 系统默认为@protected权限
@private | 只能在本来中访问,不能继承给子类 |

修饰符的使用

  1. #import <Foundation/Foundation.h>
    2.   3. @interface Person : NSObject {
    4.   5.     // 表示_name与_age两个成员变量是公开的,任何地方都可以访问
    6.     @public
    7.     NSString *_name;
    8.     NSInteger _age;
    9.   10.     // 表示_height成员变量是私有的,只有自己访问,不能被继承
    11.     @private
    12.     float _height;
    13. }
    14.   15. @end

继承注意事项

  1. OC中的继承为单继承,也就是说,一个子类,只能有一个父类;
  2. 被继承的类成为父类(或超类),继承其他类的类,称为子类。