OC的三大特性

作者: VampireJune | 来源:发表于2018-09-18 20:30 被阅读0次

    面向对象的三大特征:

    成员变量的封装、继承、多态

    1.成员变量的封装 encapsulation : setter getter 方法

    • 好处:意义在于保护、防止,代码或数据,被我们无意中破坏

      • 过滤不合理的值
      • 屏蔽内部的赋值过程
      • 让外界不必关心内部的细节
    • setter 方法

      • 作用:提供一个方法给外界设置成员变量值,可以在方法里面对参数进行相应过滤
      • 命名规范:
        1> 返回值一定是 void
        2> 方法名必须以 set 开头
        3> set后面跟上成员变量的名称,成员变量的首字母必须大写
        4> 一定要接收一个参数,而且参数类型跟成员变量类型一致
        5> 形参的名称不能跟成员变量名一样
    • getter 方法

      • 作用:返回对象内部的成员变量
      • 命名规范
        1> 肯定有返回值,返回值类型肯定与成员变量类型一致
        2> 方法名跟成员变量名一样
        3> 不需要接收任何参数
    • 成员变量

      • 命名规范:一定要以下划线 _ 开头
      • 作用
        1> 让成员变量getter方法的名称区分开
        2> 可以跟局部变量区分开,一看到下划线_开头的变量,一般都是成员变量
    @interface VampireJune : NSObject
    {
      // 成员变量尽量不要用 @public 
      // @public 
      int _age;
    }
    // setter 方法 声明
    - (void)setAge:(int)age;
    // getter 方法 声明
    - (int)age;
    
    @end
    
    @implementation VampireJune
    // setter 方法 实现
    - (void)setAge:(int)age
    {
      // 这里可以对传进来的参数进行过滤
      _age = age;
    }
    // getter 方法 实现
    - (int)age
    {
      return _age;
    }
    @end
    
    • 动态检测

      • OC是在运行过程中才会检测对象有没有实现相应的方法
    • 类方法

      • 都是以加号 + 开头

      • 只能由类名来调用

      • 类方法不能访问成员变量(实例变量)

      • 可以允许类方法对象方法 同名

      • 对象方法中可以调用类方法

      • 类方法的好处和使用场合

        • 不依赖于对象,执行效率高
        • 能用类方法,尽量用类方法
        • 场合:当方法内部不需要使用到成员变量时,就可以改为类方法
    @interface VampireJune : NSObject
    - (void)run;
    @end
    
    @implementation VampireJune
    - (void)run
    {
      // 执行一些代码
    }
    @end
    
    int main()
    {
      // 调用 run 类方法
      [Person run];
      return 0;
    }
    
    • self 指针 : 指向了当前方法调用者
      • 谁调用了当前方法,self就代表谁

        • self出现在对象方法中,self就代表对象
        • self出现在类方法中,self就代表
      • 使用细节

        • 对象方法利用self->成员变量名访问当前对象内部的成员变量
        • [self 方法名]可以调用其他对象方法\类方法
        • 出现的地方:所有OC方法中(对象方法\类方法),不能出现在函数里
      • 成员变量局部变量同名时,采取就近原则,访问的是局部变量

      • self访问成员变量,区分同名的局部变量

    :对象方法中 可以使用类方法 !!但不能使用 self调类方法,会造成死循环

    2.继承 inheritance :类与类之间的关系

    • 继承是一种语法
    • 单继承
    • 基本上所有根类都是NSObject
    • @interface 类名 后面的冒号 : 就是继承[英文冒号]
    • 父类/超类:superclass
    • 子类:subclass/subclasses
    @interface VampireJune : NSObject // 继承自 NSObject 类
    @end
    
    • 好处

      • 抽取重复代码
      • 建立了之间的关系
      • 子类可以拥有父类中的所有成员变量和方法
    • 坏处

      • 耦合性太强 [当父类没有了,子类就不能用了]
    • 注意点
      1.重写子类重写实现父类中的某个方法,覆盖父类以前的做法
      2.父类必须声明在子类的前面
      3.子类不能拥有和父类相同名称的成员变量
      4.调用某个方法时,优先去当前中找,如果找不到,去父类中找
      5.类方法同 4. 理

    • 使用场合

      • 当两个拥有相同属性和方法时,就可以将相同的东西抽取到一个父类
      • A类拥有B类中的部分属性和方法时,可以考虑让B类继承A类
      • BA 时,即A``B是同一类型物体,如,A``B均是人,或均是动物
      • 继承:B 是 A
      • 组合:B 拥有 A
    - 继承 :
    @interface A : NSObject
    {
       int _age;
    }
    @end
    
    @interface B : A
    {
       int _weight;
    }
    @end
    
    - 组合 :
    @interface A : NSObject
    {
       int _age;
    }
    @end
    
    @interface B : NSObject 
    {
       A *_a;
       int _weight;
    }
    @end
    
    • super

      • 作用
        • 直接调用父类的某个方法
        • super处在对象方法中,就会调用父类对象方法
        • super处在类方法中,就会调用父类类方法
    • 使用场合

      • 子类重写父类的方法时,保留父类的方法,不完全覆盖

    3.多态 Polymorphism :多种形态

    • 没有继承就没有多态
    • 代码的体现:父类类型的指针指向子类对象
    @interface Animal : NSObject 
    - (void)eat;
    @end
    
    @implementation Animal
    - (void)eat
    {
      NSLog(@"------%@------吃东西------",self);
    }
    
    @interface Dog : Animal 
    - (void)run; // Dog 特有的方法,父类 Animal 没有,验证多态局限性
    @end
    
    @implementation Dog
    - (void)run
    {
      NSLog(@"------Dog------跑起来------");
    }
    
    - (void)eat
    {
      NSLog(@"------Dog------吃东西------");
    }
    @end
    
    int main()
    {
      Dog *d = [Dog new]; // Dog 类型
    
      // 多态 :`父类指针`指向`子类对象`
      Animal *a = [Dog new];
    
      // 调用方法时,会检测对象的真实类型(这就是动态检测)
      [a eat];
    
      // 这也是多态
      NSObject *n = [Dog new];
      NSObject *n2 = [Animal new];
    
      // 这样是不合理的,OC是弱语法,虽然编译器不报错,只是警告,但是也不要这么写
      // Dog *d = [Animal new]; 
    
      return 0;
    }
    
    • 好处
      • 如果函数\方法参数中使用的是父类类型,可以传入父类、子类对象
    @interface Cat : Animal 
    @end
    
    @implementation Cat
    - (void)eat
    {
      NSLog(@"------Cat------吃东西------");
    }
    @end
    
    // 专门用来喂动物的函数
    void feed (Animal *a)
    { // 如果参数中使用的是父类类型,可以传入父类、子类对象
      [a eat];
    } // 只写一个方法,节省了写多个方法的代码
    
    int main()
    {
      Animal *a = [Animal new];
      feed(a);
    
      Dog *d = [Dog new];
      feed(d);
    
      Cat *c = [Cat new];
      feed(c);
    
      return 0;
    }
    
    
    • 局限性
      • 父类类型的变量 不能 直接调用子类特有的方法
      • 必须强转子类类型变量后,才能直接调用子类特有的方法
    int main()
    {
      // 使用多态 调用 `run` 方法
      Animal *a = [Dog new];
      // [a run]; // 从语法角度上,这样不合理
      // 编译器肯定先去 `Animal` 里找 `run` 方法
      // 编译器找不到 `run` 方法,只报出一个警告
      // 因为调用对象方法是动态绑定,动态检测对象的真实类型
      // 然后就会去 `Dog` 里面找 `run` 方法,还是运行成功
      // 这样写不好,可以强制转换,将 `a` 转换为 `Dog *` 类型的变量
      Dog *dd = (Dog *)a;
      [dd run];
    
      Dog *d = [Dog new];
      [d run];
    
      return 0;
    }
    

    相关文章

      网友评论

        本文标题:OC的三大特性

        本文链接:https://www.haomeiwen.com/subject/qkfmnftx.html