• OC:继承、初始化方法、便利构造器


    A继承 的作用就是为了,节省代码。
         继承 :子类会继承父类 里面所有的内容
         思想 :凡是继承过来的实例变量和方法 都是自己的(是从父类遗传过来的)
         继承的使用场景 : 当我们多个类有部分相同特征和行为时,我们就可以把相同的部分放到同一个类里面,让下一个类继承即可
         对于方法,只要声明了方法的接口,外部都可以访问到
         父类 :基类 就是没有父类的类,就是继承的上层(superclass),就叫做基类 祖宗类 OC里面 NSObject。继承的下层是子类(subclass)
    B.重写父类的方法: 如果在子类里面出现和父类方法重名的方法,系统就会认为他是对该方法的重写

    代码demo

    #import <Foundation/Foundation.h>
    #import "Person.h"
    #import "Student.h"
    #import "CollegeStudent.h"
    
    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            // insert code here...
            NSLog(@"Hello, World!");
            Person *per = [[Person alloc]init];
    //        [per test];//验证出来 self
            NSLog(@"%@",per);
            Person *per2 = [[Person alloc]init];
    //        [per2 test];
            NSLog(@"%@",per2);
            //测试 Student 继承于 person
            Student *stu = [[Student alloc]init];
            [stu name];
            //父类里的方法、行为子类也会继承过来
    //        [stu test];//这里的 test 方法就是自己的方法了
            [stu test];//子类对父类的重写
            CollegeStudent * col  = [[CollegeStudent alloc]initWithName:@"" gender:@"" age:23 num:1501 score:95 academy:@"大学本科" majory:@"软件工程"];
            NSLog(@"%@",[col name]);
        }
    
        return 0;
    }
    
    
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    {
        @protected
        NSString  *_name;
        NSString  *_gender;
        NSInteger _age;
    }
    -(void)setName:(NSString *)name;
    -(void)setGender:(NSString *)gender;
    -(void)setAge:(NSInteger)age;
    //getter
    -(NSString *)name;
    -(NSString *)gender;
    -(NSInteger)age;
    //
    -(id)initWithName:(NSString *)name
               gender:(NSString *)gender
                  age:(NSInteger)age;
    -(void)test;
    @end
    
    #import "Person.h"
    
    @implementation Person
    -(void)setName:(NSString *)name{
        _name = name;
    }
    -(void)setGender:(NSString *)gender{
        _gender = gender;
    }
    -(void)setAge:(NSInteger)age{
        _age = age;
    }
    //getter
    -(NSString *)name{
        return _name;
    }
    -(NSString *)gender{
        return _gender;
    }
    -(NSInteger)age{
        return _age;
    }
    //
    -(id)initWithName:(NSString *)name
               gender:(NSString *)gender
                  age:(NSInteger)age{
        _name = name;
        _gender = gender;
        _age = age;
        return self;
    }
    -(void)test{
        NSLog(@"我是Person");
    }
    @end
    
    
    #import <Foundation/Foundation.h>
    #import "Person.h"
    
    @interface Student : Person
    {
        /*
         继承 的作用就是为了,节省代码。
         继承 :子类会继承父类 里面所有的内容
         思想 :凡是继承过来的实例变量和方法 都是自己的(是从父类遗传过来的)
         继承的使用场景 : 当我们多个类有部分相同特征和行为时,我们就可以把相同的部分放到同一个类里面,让下一个类继承即可
         对于方法,只要声明了方法的接口,外部都可以访问到
         父类 :基类 就是没有父类的类,就是继承的上层(superclass),就叫做基类 祖宗类 OC里面 NSObject。继承的下层是子类(subclass)
         */
        NSInteger _num;
        CGFloat   _score;
    }
    //setter  getter
    //- (void)setName:(NSString *)name;
    //- (void)setGender:(NSString *)gender;
    //- (void)steAge:(NSInteger)age;
    - (void)setNum:(NSInteger)num;
    - (void)setScore:(CGFloat)score;
    - (void)test;//系统会识别为子类重写父类的方法
    //
    //- (NSString *)name;
    //- (NSString *)gender;
    //- (NSInteger)age;
    - (NSInteger)num;
    - (CGFloat)score;
    //
    -(id)initWithName:(NSString *)name
               gender:(NSString *)gender
                  age:(NSInteger)age
                  num:(NSInteger)num
                score:(CGFloat)score;
    @end
    
    #import "Student.h"
    
    @implementation Student
    //- (void)setName:(NSString *)name{
    //    _name = name;
    //}
    //- (void)setGender:(NSString *)gender{
    //    _gender = gender;
    //}
    //- (void)steAge:(NSInteger)age{
    //    _age = age;
    //}
    - (void)setNum:(NSInteger)num{
        _num = num;
    }
    - (void)setScore:(CGFloat)score{
        _score = score;
    }
    - (void)test{
        //重写父类的方法: 如果在子类里面出现和父类方法重名的方法,系统就会认为他是对该方法的重写
        /*
         重写从父类继承过来的方法:
         1. 完全以子类的实现为主,父类的实现内容就被丢弃
         2. 完全以父类的实现为主,没有子类的实现内容
         3. 既有父类里面的实现内容,又有子类的实现内容
         */
        //对于 3
        [super test];//这是从父类里继承  super 继承父类里对该方法的实现内容
        NSLog(@"这是Student类的重写方法");
    }
    //
    //- (NSString *)name{
    //    return _name;
    //}
    //- (NSString *)gender{
    //    return _gender;
    //}
    //- (NSInteger)age{
    //    return _age;
    //}
    - (NSInteger)num{
        return _num;
    }
    - (CGFloat)score{
        return _score;
    }
    //
    -(id)initWithName:(NSString *)name
               gender:(NSString *)gender
                  age:(NSInteger)age
                  num:(NSInteger)num
                score:(CGFloat)score{
        _name = name;
        _gender = gender;
        _age = age;
        _num = num;
        _score = score;
        return self;
    }
    @end
    
    #import "Student.h"
    
    @interface CollegeStudent : Student
    {
        NSString *_academy;//学院
        NSString *_major;//专业
    }
    - (void)setAcademy:(NSString *)academy;
    - (void)majory:(NSString *)majory;
    - (NSString *)academy;
    - (NSString *)majory;
    //
    - (id)initWithName:(NSString *)name
                gender:(NSString *)gender
                   age:(NSInteger)age
                   num:(NSInteger)num
                 score:(CGFloat)score
               academy:(NSString *)academy
                majory:(NSString *)majory;
    
    @end
    
    #import "CollegeStudent.h"
    
    @implementation CollegeStudent
    - (void)setAcademy:(NSString *)academy{
        _academy  = academy;
    }
    - (void)setmajory:(NSString *)majory{
        _major = majory;
    }
    - (NSString *)academy{
        return _academy;
    }
    - (NSString *)majory{
        return _major;
    }
    - (id)initWithName:(NSString *)name
                gender:(NSString *)gender
                   age:(NSInteger)age
                   num:(NSInteger)num
                 score:(CGFloat)score
               academy:(NSString *)academy
                majory:(NSString *)majory{
        //1.继承父类的初始化方法里的实现内容
         self = [super initWithName:name gender:gender age:age num:num score:score];//继承    // initWithName:name 有一个ID类型返回值
        // self 在这里指代一个 类的对象
        //如果在父类的方法 initWithName:name 里面没有实现 则会崩溃 此时self 里面就会是空的
    //    if (self != Nil) {//判断前面几个实例变量赋值成功
        //2. 对 self 的判断。如果 self 不为空 说明弗父类的初始化方法已经成功
        //self 不为空,意味着对象已经创建,赋值成功 ??,在对象已经存在的前提下才能为其赋值
        if (self) {
            _academy = academy;
            _major= majory;
        }
        //3. 如果在 OC里面如果只声明,没有实现,就会崩溃
    //    _name = name;
    //    _gender = gender;
    //    _age = age;
    //    _num = num;
    //    _score = score;
            return self;
    }
    @end
    View Code 类的继承

    1.在初始化方法里调用 super 需要当前类的对象去接收。 如;self = [super initWithName:name gender:gender age:age num:num score:score];   self 指代当前的对象,存储当前对象的地址

    对象都是用指针去指向。

    2.if (self) {//这里的判断只是一种安全处理(在这讨论了 if 究竟有没有意义,已经证明是必要的,if()是一种安全处理,如果在父类的赋值方法里,返回为 Nil 这里把if 语句注释 下面的赋值语句 就会 崩溃)
            _academy = academy;
            _major= majory;
        }
    3.注意:CollegegStudent * stu1;//这一句并没有创建对象,因为对象的 创建首先要开辟内存,然后初始化,这都是在堆中 操作,而 改代码是在栈中操作,仅仅是一个指针而已。我们通常叫 stu1 是对象,是因为他指向堆中的内存,实际上他是一个指针。有的时候,我们可以写一个临时的指针用来存放一些类的对象。

    4.注意:对象的实例变量、 方法在使用前,必须保证对象的存在。

    self = [super initWithName:name gender:gender age:age num:num score:score];//调用父类的方法去完成对公共的特征(共有的实例变量)赋值,然后把该对象接收,然后判断这个对象是否存在,如果存在就为接下来的实例变量赋值
    5.初始化方法 alloc、 init  都是继承自 NSObject 类
    6.便利构造器 
     //遍历构造器 快速创建对象 内部其实是一个对象的创建的两个步骤 是一个类方法 (Teacher.h文件)
    + (id)teacherWithName:(NSString *)name
                   gender:(NSString *)gender
                      age:(NSInteger)age
                   salary:(NSString *)salary
                    hobby:(NSString *)hobby;
    //内部封装了创建对象的两个步骤:开辟空间  初始化(Teacher.m 文件)
    //遍历构造器 是一个简单地封装 是 类名开头  (比较初始化方法 必须是 init 开头 遵循 initWith.... 才可以用 super 去接受初始化方法)
    + (id)teacherWithName:(NSString *)name
                   gender:(NSString *)gender
                      age:(NSInteger)age
                   salary:(NSString *)salary
                    hobby:(NSString *)hobby{
        Teacher * tea = [[Teacher alloc]initWithName:name gender:gender age:age salary:salary hobby:hobby];
        return tea;
    }
      //遍历构造器 快速创建对象 内部其实是一个对象的创建的两个步骤 是一个类方法(main.m 文件里)
            Teacher * tea = [Teacher teacherWithName:@"张老师" gender:@"男" age:24 salary:@"一月6000¥" hobby:@"吃饭、睡觉、打豆豆"];
            NSLog(@"%@ %@ %ld %@ %@",[tea name],[tea gender],[tea age],[tea salary],[tea hobby]);
     //把相同的实例 方法放到一起,供继承用
     //继承的特点总结
    继承具有单向性:只能是A 继承 于 B  反过来 B不能继承 于 A
    继承具有传递性:A继承于 B ,B继承于 C  ,A就拥有 B和 C 的所有的实例变量和方法
     对继承过来的方法的重写(注意点)
     // OC 里面方法的调用(执行):
    1.消息发送机制 [recevier  message]
    2.方法执行的流程:[stu test ]   先发送一个消息test 给 对象 stu ,stu 就根据 stu 存储的地址,找到对应的堆去空间,会查看实例变量 isa ,看 isa 里面存储的类,然后根据类去确定当前对象是哪个类的对象。确定完之后就会检查这个类里有没有这个test方法。如果有就调用成功,如果没有就 crash
     
     
     
     
     
     
  • 相关阅读:
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
    Careercup
  • 原文地址:https://www.cnblogs.com/benpaobadaniu/p/4723268.html
Copyright © 2020-2023  润新知