zoukankan      html  css  js  c++  java
  • Object-C Categories和Protocols

    Category

    要扩展一个不可修改的类,通常的做法是为该类创建一个子类,在子类中实现想要实现的方法,在Object-C中,可以通过category来实现,并且实现方式更为简单。

    现在有如下定义:一个包含4个方法的Fraction类

    1 @interface Fraction : NSObject
    2 @property int num, den;
    3 
    4 -(void) setTo:(int) n over:(int) d;
    5 -(void) reduce;
    6 -(double) converToNum;
    7 -(void) print;
    8 @end

    现在要为该类增加4个方法,分别为加法、减法、乘法和除法:

     1 // 定义category文件:FractionMathOps.h文件
     2 // 由于category是扩展文件,所有首先需要引入原文件
     3 #import "Fraction.h"
     4 
     5 @interface Fraction (MathOps)
     6 -(Fraction *) add: (Fraction *) f;
     7 -(Fraction *) mul: (Fraction *) f;
     8 -(Fraction *) sub: (Fraction *) f;
     9 -(Fraction *) div: (Fraction *) f;
    10 @end
    11 
    12 // 可选的将implementation定义在interface文件中,或者定义在单独的FractionMathOps.m文件中
    13 @implementation Fraction (MathOps)
    14 -(Fraction *) add : (Fraction *) f
    15 {
    16     ....
    17 }
    18 ....
    19 @end

    通过上述方法定义的category不能为原类追加成员变量,若需要追加成员变量,在定义category时不能填写名字,如:

     1 #import "Fraction.h"
     2 
     3 @interface Fraction ()
     4 @property int uniqueID;
     5 
     6 -(void) doStuffWithUniqueID: (int) theID;
     7 @end
     8 
     9 // -------------------------------------------------------
    10 
    11 // implementation实现部分,注意,Fraction后面没有括号()
    12 @implementation Fraction
    13 @synthesize uniqueID;
    14 
    15 -(void) doStuffWithUniqueID: (int) theID
    16 {
    17     ...
    18 }
    19 @end

    通过这种方法为类追加的所有方法都是private属性的,所以只希望类本事使用这些方法,这是一个好办法。

    若使用category追加原类中已经方法时,原类中的方法会被覆盖,且无法调用原类中的方法。

    可以为一个类创建多个category,若多个category文件中定义了同一个方法,Object-C无法确定具体会调用那个方法。

    同时需要注意,为一个类添加category,受影响的不仅仅是该类,也包括该类的子类在内。

    Protocols和Delegation

    Protocol是指一系列可在多个类中共享的方法,这些方法并没有特定的implementation去实现,其实就是java中的接口。

    protocol中的方法有些可以选择性的实现,有些则必须被实现

    定义protocol,只需要使用@protocol,后面接protocol的名字,之后开始像在interface中声明方法那样声明protocol方法,所有方法声明以后,以@end结尾。

    在Foundation框架中,

    1 @protocol NSCopying
    2 - (void)copyWithZone: (NSZone *)zone;
    3 @end 

    定义一个是否需要必须被实现的方法:@required和@optional,默认为@required。

    @protocol MyProtocol
    @required // 该命令可以省略
    - (void) print1; // 必须被实现
    @optional 
    - (void) print2; // 可以不被实现
    @end

    一个类若要实现一个或多个protocol,只需将protocolName放到尖括号"<>"中追加到@interface后面既可,多个protocols之间使用逗号","分割。

    1 @interface MyObj: NSObject <NSCopying>

     在上述代码中,由于系统已经知道了NSCopying的定义,所以无需在interface中定义NSCopying protocol。

    若一个类实现了一个或多个protocol,该类的子类同样会实现这些protocols

    可以使用conformsToProtocol:方法去判断一个对象是否实现了指定的protocol,如:

    1 id currentObj;
    2 ...
    3 if ([currentObj conformsToProtocol: @protocol (Drawing)] == YES)
    4 {
    5     ...
    6 }

    在上述代码中,通过使用@protocol (protocolName)的方式产生一个protocol对象 

    1 // 声明一个必须实现Drawing protocol的类实例
    2 // 若currentObj类中没有实现给protocol,则编译器会发出警告信息
    3 id <Drawing> currentObj;

    定义一个protocol时,可以指定该protocol继承另一个protocol:

    1 // MyPro1 继承MyPro
    2 // 此时实现MyPro1的类也必须实现MyPro中必须要被实现的方法
    3 @protocol MyPro1 <MyPro>
    4 ...
    5 @end

    在category中实现protocol

    1 @interface MyObj (stuff) <MyPro>
    2 ...
    3 @end

    可以将MyPro的实现放到stuff中

    1 Fraction *frac=[[Fraction alloc] initWithNumerator: 3 denominator: 5];
    2 <Printing1> p1=frac;
    3 [p1 print1];
    4 id<Printing1,Printing2,Printing3> p2=frac;
    5 [p2 print2];
    6 [p2 print3];
  • 相关阅读:
    swoole 安装方法 使用即时聊天
    git的介绍以及简单应用
    curl的应用
    linux下监听和同步代码配置
    mac skim 修改背景色
    php 编译安装的一个 configure 配置
    mac mysql error You must reset your password using ALTER USER statement before executing this statement.
    yii2 控制器里 action 大小写组合造成的路由问题
    warning : json_decode(): option JSON_BIGINT_AS_STRING not implemented in xxx
    redis 自启动脚本
  • 原文地址:https://www.cnblogs.com/gbyukg/p/3280180.html
Copyright © 2011-2022 走看看