zoukankan      html  css  js  c++  java
  • 【Objective-C 篇】 ☞ 6. 封装、继承、组合与聚合、多态

    面向对象的三大特性: 封装, 继承, 多态

    1. 封装

    1.1 基本概念

    将零散的东西组合起来。

    • 广义上封装指:将代码封装成函数,将实例变量和方法封装成类,将类封装成框架....
    • 面向对象中的封装指:封装属性和方法放在一个对象中,只给外界公开访问的接口,而且把具体实现隐藏起来。

    1.2 封装的好处

    提高可读性,可维护性,可扩展性

    1.3 OC中的封装

    OC语言天然就是封装好的。

    定义一个类时,@interface部分就是给外界公开的访问接口。@implementation部分就是隐藏起来的具体实现。

    .h文件中写的是公开的接口

    .m文件中写的是隐藏的实现

    //私有方法,只要不在头文件的接口部分声明的方法就是私有方法

    2. 继承

    2.1 概念

    继承是一种代码复用技术(代码重复使用)。是类与类之间的一种关系(“is a”关系)

    B类继承了A类。A类叫B类的父类,B类叫A类的子类。

    其他语言中还有基类,派生类的概念

    2.2 继承的方式

        单继承  OC, Java...., Swift    单继承指一个类只能有一个父类.

        多继承  C++支持多继承      多继承指一个类可以有多个父类.

        OC语言中的类在一颗树上,只有一个祖宗NSObject; swift不只有一颗树,是一片森林。

    2.3 OC中继承的语法

    @interface 类名 : 父类名

     

    @end

    2.4 什么情况下用继承

    理论上:

          如果两个类之间拥有is a关系,这两个类应该是继承关系

      狗是动物  Dog is a Animal.

            Animal是父类, Dog是子类

          如果两个类之间拥有has a关系,应该用组合或聚合

      计算中有一个CPU  Computer has a CPU

      组合和聚合是另一种类与类之间的关系

    实际开发中使用继承:

    先写的父类,还是先写的子类?//都可以

     

    2.5 抽象类

    C++: 纯虚函数,没有函数体的函数。存在纯虚函数的类是抽象类,不可以实例化了对象。

    Java: 抽象方法和抽象类, abstract来声明

    OC OC语言中没有抽象类和抽象方法的语法。

    派生:在子类中添加新的属性和方法

    2.6 重写:子类对父类的方法不满意时,可重写父类中的方法

               隐藏:当子类重写父类的方法后,子类中将有两个同名的方法,而从父类中继承的方法不能在类外被调用

    2.6.1 概念

    1) override 重写(覆盖): 子类不满意从父类中继承来的方法,重新将此方法实现了。

    要求:方法名和父类一样,参数类型一样,返回值一样。只有方法的实现不一样。

    2) overload 重载: OC中并不存在overload

    overload的概念是在一个范围内(比如一个类中),出现多个方法名相同的方法,这些方法的参数类型不同,导致可以同时出现,我们说,这些方法之间形成了重载的关系。

    OC中不允许同一个范围存在多个方法名相同的方法。

    -(id)initWithName:(NSString *)name andAge:(NSUInteger)age;

    -(id)initWithName:(NSString *)name andGender:(BOOL)gender; //OC中方法名不同

    OC中只有重写,没有重载

    方法的重写:子类对父类继承的方法不满意,可以在子类中重写父类的方法。

    如果重写父类的方法,优先调用子类的方法,如果子类没有重写父类的方法,则调用父类的方法。

     

    2.6.2 注意

    虽然父类中的属性是公开的,但生成的实例变量却是私有的,在子类中不能访问

    2.6.3 普通方法的重写

    如同perimeter, area, show

    方法名相同,参数类型相同,返回值相同

    2.6.4 属性的重写

    如同TRSqaure中的width,height属性

    2.6.5 特殊方法的继承和重写

    1) 初始化方法

    OC中初始化方法是会被继承的。

    继承来的初始化方法有些可以用,有些不能用。

    如果在子类中,继承自父类的初始化方法不能用(不能完成要求的初始化任务),在子类中就需要重写这个初始化方法。

    2) 类方法(工厂方法)

    类方法也可以被继承

    工厂方法自然也可以被继承,但直接继承的工厂方法名不匹配,实际开发中很少这样用。子类最好提供自己的工厂方法。

    2.7 继承的缺陷

      1) 提高了程序的复杂度,维护性和扩展性降低。 

      2) 破坏类的封装性  慎用继承!

    2.8 为什么使用继承?

      1) 代码复用 

        将子类重复的代码抽象到父类中

      2) 制定规范(规则)

        NSObject  

      3) 为了多态

        没有继承,就没有多态

    组合与聚合

      类与类之间的一种关系,比较常见;主要作用:代码复用!

    1.1 什么是组合

      表示两个对象之间是整体和部分的强关系,是“contains(包含) a”关系,要求两个类同生共死。

    生命周期完全一致,同生共死。部分的生命周期不能超越整体!

    例如:一个窗口内有按钮、标签,当窗口关闭时,窗口与按钮、标签同时销毁。

     

    1.2 组合的定义:

    @interface BRButton : NSObject

    @end

    @interface BREdit : NSObject

    @end

    @interface BRWindow : NSObject

    /**

     *  组合是两个类的强关系(要求定义成成员变量)

     *  1.在对象初始化时给实例变量赋值(同生共死)

     *  2.不能在类的外部对实例变量访问/赋值

     */

    {

        BRButton *button;

        BREdit *edit;

    }

    @end

     

      组合Demo:

        

        

    1.3 组合的优缺点:

    优点:

    1)当前对象只能通过所包含的那个对象去调用其方法,所以所包含的对象的内部细节对当前对象是不可见的。

    2)当前对象与包含的对象是一个低耦合关系,如果修改包含对象的类中代码,不需要修改当前对象类的代码。

    3)当前对象可以在运行时动态的绑定所包含的对象。可以通过set方法给所包含对象赋值。

    缺点:

    容易产生过多的对象

    为了能组合多个对象,必须仔细对接口进行定义。

     

    1.4 什么是聚合

    表示两个对象之间是整体和部分的弱关系,是”has a”关系,不要求两个类同生共死。

    生命周期不一致,一个类无法控制另一个类的生死。部分的生命周期可以超越整体。

    例如:电脑和鼠标,电脑被销毁时,鼠标可以留下在其他电脑上继续使用。

    1.5 聚合的定义

    @interface BRMouse : NSObject

    @end

    @interface BRComputer : NSObject

    //聚合是两个类的弱关系,在类的外部给实例变量赋值(要求定义成属性)

    @property BRMouse *mouse;

    @end

     

      聚合Demo

        

    1.6 聚合的优缺点:

    优点:

    1)被包含的对象通过包含它们的类来访问

    2)很好的封装

    3)被包含的对象内部细节不可见

    4)可以在运行时动态定义聚合的方式

    缺点:

    1)系统可能会包含太多对象

    2)当使用不同的对象时,必须小心定义的接口。

    组合和聚合的生命周期不一样,组合是同生共死(关系紧密);聚合没有特别的关系。

     

    1.7  类与类之间常见的三种关系:继承、组合、聚合

      1) 继承(继承的主要目的:代码复用,制定规范,为了多态)  慎用继承!(is a关系才用继承,否则滥用继承)

      2) 组合和聚合(单纯的为了代码复用)

              组合和聚合的主要目的:是为了代码的复用。

       

    应用场景:(代码的重复使用。如果想使用别人的代码,组合、聚合在一起就可以了)

    实际开发中,如果为了复用代码,提倡使用组合或聚合来复用,而不用继承。即是把一个类作为另一个类的属性。(整体与部分)

     

    一个类想使用另一个类的方法?怎么实现...

    1.继承:我继承你,我就可以直接调你的方法(提高程序的复杂度…不建议用!

    2.组合/聚合:把你变成我的一部分(即你是我的属性),我可以通过访问你去调用你的方法![.你 你的方法];

     

    组合:关系很紧密,同生共死。(cpu焊在主板上,主板坏了cpu也就坏了;绑在一起同生共死!)

    聚合:关系很疏远,不同生共死。(计算机是计算机,cpucpu;这个cpu可以用给这个计算机,也可以用给那个计算机,cpu可以从主板上拔下来给另一个计算机用)

    3. 多态(Polymorphism)

    3.1 什么是多态

    多种形态,引用的多种形态。对于一个引用变量,可以指向任何类的对象 (一个对外接口,多个内在实现)

     

        父类的引用指向本类或任何子类的对象,会调用不同的方法(表现出多种形态,这种表现叫多态)

    TRAnimal *animal = [[TRDog alloc]init];//父类的引用指向子类的对象

    [animal eat];//狗啃骨头 (调用子类重写的方法)

    animal = [[TRCat alloc]init];

    [animal eat];//猫吃鱼

       多态的表现:同一个引用变量s,调用相同的方法(show),显示不同的结果。

    TRShape *s=[[TRRect alloc]init]; //父类的引用指向子类的对象

    [s show]; //显示矩形  调用子类重写的方法

    s=[TRCircle alloc]init];

    [s show]; //显示圆形

     

    3.2 编译期类型和运行期类型

    编译器编译时,引用的类型叫编译期类型。

    程序运行时,引用指向的类型叫运行期类型。

           

      程序编译时按编译期类型找方法编译,程序运行时按运行期类型找方法调用。

      父类的引用指向子类的对象时,只能调用父类中有的方法。

      因为编译器在编译时是按父类来检查的,虽然运行时调用的是子类的方法,但是编译时是按父类来检查的。

    3.3 为什么用多态

    为什么用父类的引用指向子类的对象:

    为了写出更加能用(通用),兼容性更好的代码。

     

    3.4 多态的各种表现【用途】

    1)【参数多态】经常在方法的参数表现多态:参数类型使用父类型,可以传任何子类的对象

    NSObject *id类型做为方法的参数区别在于:

    NSObject *类型的引用只能调用NSObject类中有的方法。

    id类型的引用可以调用任何存在(不能瞎写)的方法。

    (一般不用NSObject *类型,用id类型替代。id有风险的,编译器根本不检查对错)

    /** 方法的参数 表现多态 */

    void showAnimal(TRAnimal *animal) {

        [animal eat];

        [animal sleep];

        //[animal watchHome];//父类中没有这个方法编译不通过

    }

    int main() {

        @autoreleasepool {

            TRDog *dog = [[TRDog alloc]init];

            showAnimal(dog);

            showAnimal([TRCat new]);

        }

        return 0;

    }

     

      2)【返回值多态】方法的返回值上表现多态

        

    3)【数组多态】在数组和集合中表现的多态

    //数组 表现多态 [多个对象同时执行eat方法]

    TRAnimal *animals[3] = {[TRAnimal new], [TRDog new], [TRCat new]};

    for (int i = 0; i < 3; i++) {

    [animals[i] eat];

    }

      

     多态无处不在!

     

     

    多态Demo

      

        

        

     

  • 相关阅读:
    [CC-TRIPS]Children Trips
    [HDU5968]异或密码
    [CC-PERMUTE]Just Some Permutations 3
    [HackerRank]Choosing White Balls
    Gym102586L Yosupo's Algorithm
    Gym102586B Evacuation
    Kattis anothercoinweighingpuzzle Another Coin Weighing Puzzle
    Gym102586I Amidakuji
    CF1055F Tree and XOR
    CF241B Friends
  • 原文地址:https://www.cnblogs.com/bossren/p/6428475.html
Copyright © 2011-2022 走看看