Object-C基础(9)——多态、类别、扩展与协议

多态

    多态的概念和产生

    变态:相同类型的对象,在同一件行为(方法),但某个对象表现成与众不同的行为(态),此时就称之为变态。

    多态:相同类型的对象,在执行同一个方法时,表现成多种的行为特征(态),此时就称之为多态。

    多态为何会产生?

          1. 支持向上转型。子类实例可以赋值给父类变量。

          2. 方法调用时总是动态绑定的。

          如果有这两点情况,程序就会产生多态。

     多态的好处:编程更加灵活。

      —— 当函数、方法需要一个父类参数时,实际可以传入给父类的任意子类的实例。类型判断和类型转换

     id类型,有点类似NSObject类型。但id类型更强大,它在编译时就支持动态解析【方法】。成员变量不行!点语法不行!

     在有些时候,希望判断某个变量所指的对象是否为指定类型的实例。

            -  [变量 isKindOfClass:类] : 判断该变量所指对象是否为指定类、及其子类的实例。

            -  [变量 isMemberOfClass:类] : 判断该变量所指对象是否为指定类的实例。

            -  + isSubcassOfClass:clazz:判断该类是否为指定类的子类。

     向上转型:Object-C支持自动装换,无需程序进行额外处理。

     向下转型(缩小转换):就必须使用强制类型转换的语法。 (类型)

包装类

      为什么要包装类:有些方法需要的参数必须是id类型(NSObject类型),但实际传入的值又是基本类型。

      此时就需要借助于包装类把基本类型的值包装为对象。

              包装

      基本类型 --> 对象

             拆包

      对象   ---> 基本类型的值

      典型地,KVC时就需要使用包装类。

      这些都不不是包装类。

       NSInteger,(32位平台上,相当于int或,64位平台上,相当于long)

       NSUInteger,  (32位平台上,相当于unsignedint或,64位平台上,相当于unsigned  long)

       CGFloat(32位平台上,相当于float、64位平台,相当于double)

       NSValue和NSNumber, NSNubmer是NSValue的子类。

       NSValue是一个通用的包装类,可以包装基本类型、指针、对象id等。实际上用的少。

       NSNumber:用于包装数值类型(short、int、long、long long、float、double、char、BOOL、枚举)。

          + numberWithXxx: 将基本类型的值,包装为NSNumber对象。

          - initWithXxx: 将基本类型的值,包装为NSNumber对象。

          - xxxValue:将包装类对象拆箱出所包装的值。

处理对象

     - description方法

       该方法来自NSObject,因此所有类的实例都可调用该方法。

       当程序输出一个对象时,实际上就是输出该对象的description方法的返回值。

       NSObject的description方法的默认返回 <类名: 地址>

       如果程序希望输出对象时,能看到该对象的内部状态(各成员变量的值),那么最好就重写description方法。

     - isEqual:

     如果用==判断两个指针变量是否相等,程序要求两个指针变量指向内存中同一个对象才算相等。即要求两个指针变量保存的地址相等。

     在某些时候,程序希望根据业务要求来判断两个对象是否相等 —— 比如对于两个苹果,只要他们品种、重量相等,即可认为它们相等。

      再比如在某些社交APP中,只要两个用户的id相等,即可认为它们相等。此时就考虑重写isEqual:方法。

类别(category,分类)

      假如项目需要为一个已有类(比如NSNumber)增加新的方法,有如下两种做法:

      - 通过继承创建NSNumber的子类,然后在子类中增加新的方法。

        这种方式的结果是:NSNumber的程序员扩展的子类就具有了新方法,但NSNumber类本身依然没有新的方法。

        NSNumber类簇中其他类更加没有这些新的方法。

        更糟糕的是:Object-C的很多类采用的是一种类簇(cluster)设计,NSNumber、NSDate等都是这种设计。

        类簇设计:Cocoa框架提供一个公开的类,但在该类底层隐藏大量的子类,这个公开的类就被称为类簇的前端类。

        当程序面向公开API(比如NSNumber、NSDate)等编程,但实际上系统创建的只是该类的子类的实例。

      - 利用类别:类别可以在不修改已有类的代码的基础上,为已有的类增加新的方法。

      Object-C中并不太喜欢用继承。

      类别的语法:

        @interface 已有的类 (类别名)

        方法声明

        @end

        【注意】:类别只能添加方法,不能添加成员变量,因此也不能使用@property来合成属性。

        @implementation 已有的类 (类别名)

        方法实现

        @end

        类别:体现Object-C语言的动态性,通过类别,程序可以在不修改代码的基础上,为已有的类,动态地增加新的方法。 

        类别可用于对类进行模块化设计。

        在Cocoa框架中,有很多类非常庞大,比如NSWindow类,它包含100多个方法,这个类的代码就非常多,程序难以维护。

         此时就可以考虑如下设计:

         (1)建一个NSWindow类,该类中只定义最核心的20个方法,这个类代码就少的多了。

         (2)为了NSWindows创建多个类别,每个类别再额外定义10来个方法,每个类别的代码也不会太多。

             此处通过类别定义的方法最后也会添加NSWindow中。

          通常来说,集中某些功能会放置到特定的类别中。

          NSString也采用了类别进行模块化设计。该String类中用于操作文件路径的相关方法,都放在特定分类(模块)中实现。

       类别还可以用于暴露私有方法。

           Object-C的方法之所以能被隐藏,是因为在类的头文件部分没有声明该方法。

           为了暴露该方法,只要使用类别的头文件重新声明该方法即可。

           而且在使用时,也很灵活:

           1. 如果你希望还是隐藏该方法,只要导入该类原始的头文件即可。

           2. 如果你希望把隐藏方法暴露出来,你就应导入类别的头文件即可。

       还可用于定义非正式协议。

扩展(extension)

      扩展,相当于一个匿名的类别。

      但扩展即可添加新的方法,也可添加新的成员变量。当然也可以用property合成属性。

        @interface 已有的类 ()

        {

            // 成员变量

        }

        方法声明

        @end

       扩展定义,通常直接放在实现部分即可。

                而且扩展添加的方法,通常直接在类的实现部分实现它们即可。

       如果将扩展定义放在类的实现部分,那么该扩展中定义的方法、成员变量都是被隐藏的。

       如果希望将扩展定义的东西也暴露出来,那么就需要使用额外的头文件来定义扩展,并使用使用时导入扩展的头文件。

协议

      协议,体现的一种高层次的规范,这种通常用于制定某种规定,用于被类来遵守。

      Object-C,某个类,遵守(实现)了xxx协议。

      【协议,自身不提供实现。】

      Java中的接口,与OC的协议完全一样的。

      还可用于定义非正式协议(unformalprotocol)。  ——用到的相对较少

        非正式协议,就是为NSObject定义一个类别的头文件部分即可——因为协议是不提供实现的!!

        实现非正式协议,其实是通过继承NSObject的指定分类来实现的。

        非正式协议,编译不会检查实现类必须实现协议中的方法。

                   如果实现类要调用非正式协议中的方法,必须自己保证在实现类中实现该方法。 

       正式协议

        @protocol 协议名 <父协议1, 父协议2, ...>

        // 方法声明

        @end

        协议没有实现部分!

        1. Object-C类是单继承的,但协议是多继承的。协议,可以没有父协议的。

        2. 协议只能继承继承,协议不能继承类。

       遵守协议

         @interface 类名 : 父类 <协议1, 协议2, 协议3...>

         @end

         遵守协议,就是在父类后面用尖括号列出所有需要遵守的协议。

         如果一个类遵守了正式协议,编译器会要求实现类必须实现协议中所有方法,编译器会报警告。

         正式协议中可选方法 - 遵守协议的类,可实现该方法,也可不实现该方法。

         此时应该使用@optional来限定该方法。

         @required要求该方法必须被实现 —— 默认就是它,因此一般不写。

      协议的典型用途: 协议与代理。

         无论在Cocoa开发,开始CocoaTouch开发中,这都是非常常见。

         在我们Cocoa、Cocoa Touch开发中,经常会需要设置代理对象,而代理对象总是要实现特定的协议,并实现协议中特定的方法。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值