黑马——Objective-C学习笔记<十>:分类和协议

 ——- android培训IOS培训、期待与您交流! ———-

分类

分类(category)可以模块的方式向现有的类添加方法。

它提供了一种简单的方式,可以将类的定义模块化到相关方法的组或分类中。它还提供了扩展现有类定义的简便方式,并且不必访问类的源代码,也无需创建子类。

以一个Fraction类为例,除了将两个分数相加的add:方法外,还想要拥有将两个分数相减、相乘和相除的方法。

    //Fraction类声明 
    #import <Foundation/Foundation.h> 

    @interface Fraction:NSObject 
    { 
       intnumerator; 
       intdenominator; 
    } 

    @property intnumerator,deniminator; 

    -(void) setTo:(int) nover:(int) d; 

    -(Fraction*) add:(Fraction*) f;       // 声明分数的加法函数 

    -(void) print; 

    @end 

现在,从接口部分删除add:方法,并将其添加到新分类,同时添加其他三种要实现的数学运算。看一下新MathOps分类的接口部分。

#import <Foundation/Foundation.h> 
#import "Fraction.h" 

 @interface Fraction(MathOps) 

     - (Fraction*) add:(Fraction*) f;       // 加法函数 

     - (Fraction*) mul:(Fraction*) f; // 乘法函数 

     - (Fraction*) sub:(Fraction*) f; // 减法函数 

     - (Fraction*) div:(Fraction*) f; // 除法函数 

@end 

   //#import "Fraction.h" 这里既是分类接口部分的定义,也是对现有接口部分的扩展,所以必须包括原始接口部分 

    //@interfaceFraction(MathOps) 告诉编译器正在为FFrraaccttiioonn类定义新的分类,名称为MMaatthhOOppss。 

可以在一个实现文件中定义Fraction.h接口部分中的所有方法,以及MathOps分类中的所有方法。

也可以在单独的实现部分定义分类的方法。在这种情况下,这些方法的实现部分还必须找出方法所属的分类。与接口部分一样,通过将分类名称括在类名称之后的圆括号中来确定方法所属的分类,如下所示:

    @implementation Fraction (MathOps) 

       //codeforcategorymethods @end 
关于分类的一些注意事项

A、 尽管分类可以访问原始类的实例变量,但是它不能添加自身的任何变量。如果需要添加变量,可以考虑创建子类。

B、 分类可以重载该类中的另一个方法,但是通常认为这种做法不可取。因为,重载之后,再不能访问原来的方法。

C、 可以拥有很多分类。

D、 和一般接口部分不同的是,不必实现分类中的所有方法。这对于程序扩展很有用,可以在该分类中声明所有方法,然后在一段时间之后才实现它。

E、 通过使用分类添加新方法来扩展类不仅会影响这个类,同时也会影响它的所有子类。


协议

协议的声明类似于类接口的声明,有一点不同的是,协议没有父类,并且不能定义成员变量。下面的例子演示了只有一个方法的协议的声明:

    @protocol  MyProtocol 

    -(void)myProtocolMethod; 

   @end 

协议是多个类共享的一个方法列表,协议中列出的方法没有相应的实现。如果一个类采用MyProtocol协议,则必须实现名为myProtocolMethod的方法。

通过在@interface行的一对尖括号<…>内列出协议名称,可以告知编译器你正在采用一个协议。这项协议的名称放在类名和它的父类名称之后,如下所示:

@interface AddressBook: NSObject <myProtocol>

这说明,AddressBook是父类为AddressBook的对象,并且它遵守myProtocolMethod协议。在AddressBook的实现部分,编译器期望找到定义的myProtocolMethod方法。

如果采用多项协议,只需把它们都列在尖括号中,用逗号分开:

@interface AddressBook : NSObject<myProtocol,yourProtocol>

以上代码告知编译器AddressBook类采用myProtocolMethodyourProtocolMethod协议。这次,编译器将期望在AddressBook的实现部分看到为这些协议列出的所有方法的实现。

有关协议的注意事项:

A、如果一个类遵守某项协议,那么它的子类也遵守该协议。

B、协议不引用任何类,它是无类的(classless)。任何类都可以遵守某项协议。

C、通过在类型名称之后的尖括号中添加协议名称,可以借助编译器的帮助来检查变量的一致性,如下:

id <Drawing> currentObject;

这告知编译器currentObject将包含遵守Drawing协议的对象。如果向currentObject指派静态类型的对象,这个对象不遵守Drawing协议,编译器将给出warning。

再次提到id类型,如果向currentObject指派一个id变量,不会产生这条消息,因为编译器不知道存储在id变量中的对象是否遵守Drawing协议。

D、如果这个变量保存的对象遵守多项协议,则可以列出多项协议,如下:

id <Drawing,Drawing1> currentObject;

E、定义一项协议时,可以扩展现有协议的定义。以下协议

@protocol Drawing3D <Drawing>

说明Drawing3D协议也采用了Drawing协议。因此采用Drawing3D协议的类都必须实现此协议列出的方法,以及Drawing协议的方法。

F、分类也可以采用一项协议,比如:

@interface Fraction(stuff) <NSCopying,NSCoding>

此处,Fraction拥有一个分类stuff,这个分类采用了NSCopyingNSCoding协议。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值