类的扩展(一):继承

OC中,继承于NSObject的类统称为 model 类(存字符串)

OC中,只允许单继承,无多继承,协议是间接地实现多继承的方式

继承所有的实例变量和方法,子类可以重写父类的方法


例子:Student继承于Person

Person.h文件

#import <Foundation/Foundation.h>

@interface Person : NSObject
{
    NSString *_name;
    NSString *_sex;  // default is male
    NSInteger _age;
}

// 非重写的初始化方法需要进行声明
- (instancetype)initWithSex:(NSString *)sex;
- (instancetype)initWithName:(NSString *)name;
- (instancetype)initWithAge:(NSInteger)age;
- (instancetype)initWithAge:(NSInteger)age sex:(NSString *)sex;
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex;
- (instancetype)initWithName:(NSString *)name age:(NSInteger)age;
- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age;

// 便利构造器
+ (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age;

- (void)eat;

- (void)toilet;

@end
Person.m文件

#import "Person.h"

@implementation Person

// 子类如果继承父类,那么在子类的初始化方法中(内部)必须调用父类的初始化方法

// 指定指派初始化方法,可以用来纠错
// 这个初始化方法为指派初始化方法,sex是必须有的
- (instancetype)initWithSex:(NSString *)sex
{
    // self, super均为去调用这个实例化方法的对象
    self = [super init];
    if (self) {
        _sex = sex;
    }
    
    return self;
}

// 非重写的初始化方法需要进行声明
// 在非指派初始化方法中,自己本身调用指派初始化方法
// 在这些方法中 无sex时,需要赋一个默认值
- (instancetype)init
{
    self = [self initWithSex:@"male"];
    
    return self;
}

//- (instancetype)initWithName:(NSString *)name
//{
//    self = [self initWithSex:@"male"];
//    if (self) {
//        _name = name;
//    }
//    
//    return self;
//}

- (instancetype)initWithName:(NSString *)name
{
    // 在调用时,也可通过调用自身的init方法来调用指派初始化方法
    self = [self init];
    if (self) {
        _name = name;
    }
    
    return self;
}

- (instancetype)initWithAge:(NSInteger)age
{
    self = [self init];
    if (self) {
        _age = age;
    }
    
    return self;
}

- (instancetype)initWithAge:(NSInteger)age sex:(NSString *)sex
{
    self = [self initWithSex:sex];
    if (self) {
        _age = age;
    }
    
    return self;
}

- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex
{
    self = [self initWithSex:sex];
    if (self) {
        _name = name;
    }
    
    return self;
}

- (instancetype)initWithName:(NSString *)name age:(NSInteger)age
{
    self = [self init];
    if (self) {
        _name = name;
        _age = age;
    }
    
    return self;
}

- (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age
{
    self = [self initWithSex:sex];
    if (self) {
        _name = name;
        _age = age;
    }
    
    return self;
}

// 便利构造器
 + (instancetype)initWithName:(NSString *)name sex:(NSString *)sex age:(NSInteger)age
{
    Person *per = [[Person alloc] initWithName:name sex:sex age:age];
    [per eat];
    
    return per;
}

- (void)eat
{
    NSLog(@"吃五谷杂粮");
    
    // 哪一个对象去调用一个实例化方法,那么在这个实例化方法中的self就是这个对象本身,不管这个方法是父类的还是子类的(Student调用就是stu,Person调用就是per)
    NSLog(@"self = %@", self);
    
//    [self toilet];
}

- (void)toilet
{
    // 谁去调用这个实例化方法,这个实例化方法中的self就是谁
    NSLog(@"next self = %@", self);
}

@end
Student.h文件

#import <Foundation/Foundation.h>
// 引入Person.h文件
#import "Person.h"

@interface Student : Person// 子类 : 父类

@end
Student.m文件
#import "Student.h"

@implementation Student

- (instancetype)init
{
    self = [super init];
    
    return self;
}

// 重写父类方法,不需要再次声明
- (void)eat
{
    // 子类对象调用父类方法,super代表子类对象 也要完成父类的东西
    [super eat];
    NSLog(@"吃果蔬");
    NSLog(@"func = %s", __func__);
}

- (void)toilet
{
    NSLog(@"上厕所");
    NSLog(@"__func__ = %s", __func__);
}

@end
main文件
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        Person *per = [[Person alloc] init];
        [per eat];
        NSLog(@"per = %@\n\n", per);
        
        // Student类继承于Person类
        Student *stu = [[Student alloc] init];
        [stu eat];
        [stu toilet];
        NSLog(@"stu = %@\n\n", stu);
        
        // 父类不能强转为子类 去调用子类的方法
        Person *pp = [[Person alloc] init];
//        [pp toilet];
//        [(Student *)pp toilet];
        
        // 子类可以强转为父类
        // 如果子类没有重写父类的方法,那么执行父类的方法
        // 如果子类重写了父类的方法,那么执行子类重写的方法
        Student *ss = [[Student alloc] init];
        [(Person *)ss toilet];
        
    }
    return 0;
}

 
打印结果: 

吃五谷杂粮

self = <Person: 0x100202850>

per = <Person: 0x100202850>


吃五谷杂粮

self = <Student: 0x100107090>

吃果蔬

__func__ = -[Student eat]

next self = <Student: 0x100107090>

上厕所

__func__ = -[Student toilet]

stu = <Student: 0x100107090>


next self = <Student: 0x10010c320>

上厕所

__func__ = -[Student toilet]



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值