现在的位置: 首页 > 综合 > 正文

[objective-c] Interface & Protocol & Categories

2012年07月26日 ⁄ 综合 ⁄ 共 2339字 ⁄ 字号 评论关闭

 

1  Interface(接口约定)

       Interface理解为接口概念,于JAVA\C#中的接口有所不同的是Obj-C中的接口应该理解为一种非正式协议,Obj-C中的Interface只是表明应该会处理其中声明的消息(方法),但是不是必须处理。

      clip_image002

     表明Sample Interface中,约定了应该会处理HelloWorld消息,但是Sample.m中我们可以不去实现对HelloWorld的处理,这样编译器会给出警告但是编译可以通过,但是在程序中向Sample发送该消息会引发异常。

2  Protocol(正式协议)

      Protocol(正式协议)看上去更正规一些,语义上更强烈一些:要求采用该协议的类,"必须"实现协议中约定的方法。但是比较娱乐的是,即使是号称正式协议,编译器在编译时,遇到不守规矩的情况,仍然只是给出警告。你会觉得Protocol跟Interface比起来,都是类似的概念,Protocol设计纯属多余。其实不然,Protocol存在的一个重要意义在于:

Protocol(正式协议)可以将业务中的方法定义剥离出来,形成一个单独的文件,这跟传统OO中的提取接口是不谋而合的。如果遇到二个系统需要交换数据,可以制定一套双方都遵守的Protocol,然后这二个系统中都把这个协议文件添加到项目中,实现它即可。

    这一功能,非正式协议(@interface)是做不到的。因为在Obj-C中是不允许多继承的,双方系统可能都需要继承某一个类以实现某些功能,这时候只能实现一个协议(Protocol)。 此外,Obj-C 2.0中对协议还做了一些扩展,允许把协议中的方法标识为“必须实现(@required)”和“可选实现(@optional)”二类,如果协议中的方法被标识为@optional,即使采用该协议的类不实现这些方法,编译器也不会给出警告。这样接口约定的很多作用就可以由协议来实现,不过协议中不能含有数据(但是接口约定中可以有数据成员)。

     NSObject是一个Interface也是一个Protocol,而Interface NSObject实现了Protocol NSObject,在Obj-c的OO世界中,身为万物之祖的NSObject其实也就一个"正式协议”,所以从NSObject派生出的所有类,都只是在遵守一个或多个协议而已。

3 Categories (类型分类,非正式协议)

      非正式协议并没有设计为正式协议的宽松版本,而是设计为Class Categories(类型分类)。Categories是Objective-C里面最常用到的功能之一。大体上说,Categories可以让我们给已经存在的类增加方法,而不需要增加一个子类。而且不需要知道它内部具体的实现。如果我们想增加某个framework自带的类的方法,这非常有效。如果我们想在我们程序工程的NSString能够增加一个方法,我们就可以使用Categories,不需要自己实现一个NSString的子类。比如,我们想在NSString里面增加一个方法来判断它是否是一个URL,那我们就可以这么做:

1) 在categoriesTest.h头文件中:

   1:  @interface NSString (URLDetecter)
   2:  - (BOOL) isURL;
   3:  @end

     这跟类的定义非常类似。区别就是category没有父类,而且在括号里面要有category的名字。名字可以随便取,但是习惯叫法会让人比较明白category里面有些什么功能的方法。这里是具体的实现。但是要注意,这本身并不是一个判断URL很好的实现。我们主要是为了整体的了解category的概念。

2) 在categoriesTest.m中给出实现

   1:  #import "categoriesTest.h"
   2:  @implementation NSString (URLDetecter)
   3:  - (BOOL) isURL{  
   4:    if ( [self hasPrefix:@"http://"] )    
   5:        return YES;
   6:    else 
   7:       return NO;  
   8:  }@end

3) 在main.m中使用NSString的时候如下:

   1:  NSString* string1 = @"http://www.CocoaDev.cn/";
   2:  NSString* string2 = @"Pixar";
   3:  if ([string1 isURL])  NSLog(@"string1 is a URL");
   4:  if([string2 isURL])  NSLog(@"string2 is a URL");

4)  如果在main.m没有import头文件categoriesTest.h,会有如下警告

     warning: 'NSString' may not respond to '-isURL' 

     warning: (Messages without a matching method signature

     warning: will be assumed to return 'id' and accept

     warning: '...' as arguments.

     编译器认为NSString不会对消息isURL作出回应。

     此时运行得到的结果如下:

     clip_image004

5)  如果在main.m中import头文件categoriesTest.h

     运行结果如下:

     clip_image006

     跟子类不一样,category不能增加成员变量。我们还可以用category来重写类原先的存在的方法,但是这需要非常非常小心。记住,当我们通过category来修改一个类的时候,它对应用程序里的这个类所有对象都起作用。

抱歉!评论已关闭.