Objective-C中的类目,延展,协议

Objective-C中的类目(Category),延展(Extension),协议(Protocol)这些名词看起来挺牛的,瞬间感觉OC好高大上。在其他OOP语言中就没见过这些名词,刚看到这三个名词的时候,有种感觉这是不是学习的坎?这东西难不难?能不能学会?经过本人亲自验证,这三个东西理解起来还是蛮简单的,学过C++或者Java的小伙伴对比理解还是蛮轻松的。类目(Category)就是给已有的类扩充相应的方法,扩充的方法是公有的,类目还可以起到分模块的功能,下面会详细说到。 延展(Extension)这个名词就是是匿名类目的别称,匿名类目就叫做延展,延展可以实现类方法的私有化,具体如何实现,下面有源码。协议我个人感觉和Java中的接口极为相似,在定义对象时使用协议,个人感觉和Java中得泛型有着异曲同工之妙,看下文的详细介绍吧。(本文为笔者个人总结,欢迎批评指正)。

一.Objective-C中的类目(Category)

在Objective-C比其他OOP的编程语言多了个类目,在OC中除了用继承来扩充类的功能函数外我们还可以用类目来实现。学过C++的小伙伴们是否还记得友元这个概念呢?友元就是非本类的方法可以使用本类中得变量,这也是对类方法的一个扩充,个人感觉在OC中得类目和C++中的友元有着异曲同工之妙(仅代表个人观点,欢迎批评指正),下面我们就来详细的学习一下OC中得类目吧。

提到类目呢,首先我们会问我们具体能拿类目做些什么事情呢下面做一下总结:

1.可以用类目给已有的类扩充方法

2.可以用类目把类的实现按功能模块分为不同的文件

3.可以用来扩展NSObject类的方法,也叫做非正式协议

编译环境说明:  iMac OS X 10.9 (13A603) 编译器:XCode 5.0.2版本

1.给已有的类扩充方法

在Xcode中新建CategoryTest类,在新建类中声明两个实例变量,在实现类中重写description方法,打印输出两个实例变量的值

代码如下


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

//CategoryTest.h

#import <Foundation/Foundation.h>

@interface CategoryTest : NSObject

//定义两个私有的属性

{

@private

    int ludashi1;

    int ludashi2;

}

@end

//CategoryTest.m

#import "CategoryTest.h"

@implementation CategoryTest

//重写description方法

-(NSString *) description

{

    return [NSString stringWithFormat:@"ludashi1 = %d, ludashi2 = %d", ludashi1,ludashi2];

}

@end

新建一个CategoryTest的类目,来进行对类方法的扩充,

代码如下:


1

2

3

4

5

6

7

8

9

//  CategoryTest+CategoryExtendFunction.h

//  Memory

//  Created by ludashi on 14-8-4.

//  Copyright (c) 2014年 Mr.li. All rights reserved.

#import "CategoryTest.h"

@interface CategoryTest (CategoryExtendFunction)

//利用类目扩展新的方法

-(void) extendFunction;

@end

实现文件:


1

2

3

4

5

6

7

8

9

10

11

12

13

//

//  CategoryTest+CategoryExtendFunction.m

//  Memory

//  Created by ludashi on 14-8-4.

//  Copyright (c) 2014年 Mr.li. All rights reserved.

#import "CategoryTest+CategoryExtendFunction.h"

@implementation CategoryTest (CategoryExtendFunction)

//实现扩展的方法

-(void)extendFunction

{

    NSLog(@"鲁大师,你好!我是通过类目扩展的方法!");

}

@end

测试运行结果:


1

2014-08-04 17:08:46.187 Memory[1621:303] 鲁大师,你好!我是通过类目扩展的方法!

2.对把类中不同的功能模块分成不同的文件

1.给上面的类创建两个类目,类目中分别存放实例变量的getter和setter方法,为了节省篇幅下面给出其中一个类目的事例;

接口的声明:


1

2

3

4

5

6

7

8

9

10

11

//  CategoryTest+Categgory1.h

//  Memory

//  Created by ludashi on 14-8-4.

//  Copyright (c) 2014年 Mr.li. All rights reserved.

#import "CategoryTest.h"

@interface CategoryTest (Categgory1)

//声明Category中实例变量ludashi1的getter和setter方法

-(void) setLudashi1:(int) vLudashi;

-(int) ludashi1;

@end

类目的实现文件:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

//  CategoryTest+Categgory1.m

//  Memory

//  Created by ludashi on 14-8-4.

//  Copyright (c) 2014年 Mr.li. All rights reserved.

#import "CategoryTest+Category1.h"

@implementation CategoryTest (Categgory1)

//实现ludashi1的getter和setter方法

-(void)setLudashi1:(int)vLudashi

{

    ludashi1 = vLudashi;

}

//getter方法

-(int) ludashi1

{

    return ludashi1;

}

@end

对代码测试的结果:


1

2014-08-04 17:08:46.188 Memory[1621:303] ludashi1 = 10, ludashi2 = 20

3.非正式协议

非正式协议就是给NSObject类创建的类目又叫做非正式协议, 非正式协议一般不需要进行实现,一般在子类中进行方法的重写。代码在这就不赘述啦!

类目的优缺点分析(下面有些是个人观点,不对之处请批评指正)

优点:上面的功能也是类目存在的重要原因之所在,在这就不重复了

局限性: 在类目中只可以为类添加方法,不能添加实例变量; 类目中得方法的优先级要高。

二.Objective-C中的延展(Extension)

简单的说匿名类目就是延展,在延展中定义的方法是类私有的方法只能在类的内部调用,定义延展的方式就是把类目中括号中得名字省略掉,括号保留这就是延展。其实在延展中定义的方法不是真正的私有方法和C++, Java中得方法还有所区别,在类初始化的文件中引入相应延展的头文件,其延展对应的方法也是可以访问的。是通过隐藏延展的头文件来达到方法私有 的。

定义私有方法有以下三种方式:

1.通过延展来实现方法的私有,延展的头文件独立。这种方法不能实现真正的方法私有,当在别的文件中引入延展的头文件,那么在这个文件中定义的类的对象就可以直接调用在延展中定义所谓私有的方法。demo如下:

代码如下:

延展相应的头文件,延展方法的实现在类对应的.m中给出实现方法:


1

2

3

4

5

6

#import "ExtensionTest.h"

@interface ExtensionTest ()

-(void)privateFunction1;

@end

2.第二种实现延展的方式是延展没有独立的头文件,在类的实现文件.m中声明和实现延展,这种方法可以很好的实现方法的私有,因为在OC中是不能引入.m的文件的

3.第三种实现方法私有的方式是在.m文件中得@implementation中直接实现在@interface中没有声明的方法,这样也可以很好的实现方法的私有。

Extension.m中的代码


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

#import "ExtensionTest.h"

#import "ExtensionTest_Extension1.h"

//在实现方法里声明延展

@interface ExtensionTest()

-(void) privateFunction2;

@end

@implementation ExtensionTest

//实现各种方法

-(void)publicFunction

{

    NSLog(@"publicFunction PS:我是正儿八经的公用方法,我在.h中被声明,在.m中被实现");

    //调用各种私有方法

    [self privateFunction1];

    [self privateFunction2];

    [self privateFunction3];

    

}

//实现第一个私有方法(第一种实现类方法私有化的方法)

-(void)privateFunction1

{

    NSLog(@"PrivateFunction1 PS:我是在别的头文件中定义的延展,在.m中被实现");

}

//实现第二个私有方法(第二种实现类方法私有化的方法)

-(void)privateFunction2

{

    NSLog(@"PrivateFunction2 PS:我是在本文件中定义的延展,在本文件中进行实现!");

}

//在头文件中为声明的方法在.m中直接定义是私有的方法

-(void)privateFunction3

{

    NSLog(@"PrivateFunction3: 我是在实现方法中直接定义的方法,我也是私有变量");

}

end

在main函数里进行测试,如果在main函数里引入#import "ExtensionTest_Extension1.h"也可以调用其里面声明的相应的方法

?    ?测试代码如下:


1

2

3

4

//测试延展

ExtensionTest *extension = [ExtensionTest new];

[extension publicFunction];

[extension privateFunction1];

?    ?运行结果:


1

2

3

4

5

2014-08-05 15:54:46.147 Memory[1683:303] publicFunction PS:我是正儿八经的公用方法,我在.h中被声明,在.m中被实现

2014-08-05 15:54:46.149 Memory[1683:303] PrivateFunction1 PS:我是在别的头文件中定义的延展,在.m中被实现

2014-08-05 15:54:46.149 Memory[1683:303] PrivateFunction2 PS:我是在本文件中定义的延展,在本文件中进行实现!

2014-08-05 15:54:46.150 Memory[1683:303] PrivateFunction3: 我是在实现方法中直接定义的方法,我也是私有变量

2014-08-05 15:54:46.150 Memory[1683:303] PrivateFunction1 PS:我是在别的头文件中定义的延展,在.m中被实现

三、Objective中得协议Protocol

?    ?    ?协议(protocol)提到OC中得协议个人感觉和JAVA中的接口的用法极为相似。把类中常用的方法抽象成OC中得协议,协议中只有方法的声明没有方法的实现,在protocol中可以把方法定义成@required(必须的):在使用协议的类中如果不实现@required的方法,编译器不会报错但会给出警告。还可以把protocol中的方法定义成@optional(可选的)如果在使用协议的类中不实现@optional方法,则不会警告。协议的关键字用@protocol来定义。

?    ?    ?下面是协议的一个简单demo;

?    ?    ?1.在Xcode中新建一个Protocol,命名为FirstProtocol,文件名为FirstProtocol.h . 在FirstProtocol协议中声明了两个方法,一个是@required一个是@optional的


1

2

3

4

5

6

7

8

9

10

11

12

#import <Foundation/Foundation.h>

//创建第一个protocol

@protocol FirstProtocol <NSObject>

//为protocol里加入必须实现的方法

@required

-(void)requiredFunction;

//定义可选的方法

@optional

-(void)optionalFunction;

@end

?    ?    ?2.新建一个类命名为ProtocolClass, 在ProtocolClass.h中使用FirstProtocol协议,在ProtocolClass.m文件中实现协议中得方法

?    ?    ?    ?ProtocolClass.h的代码如下:


1

2

3

4

5

#import <Foundation/Foundation.h>

#import "FirstProtocol.h"

//在普通类中实现协议的方法如下<>

@interface ProtocolClass : NSObject<FirstProtocol>

@end

?    ?    ?ProtocolClass.m的代码如下:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

#import "ProtocolClass.h"

//不实现协议中必须的方法会产生警告

@implementation ProtocolClass

//实现协议中必须的方法: required方法

-(void) requiredFunction

{

    NSLog(@"RequiredFunction PS: 我是协议中required方法,不实现我会有警告!");

}

//实现协议中可选的方法,不实现不会有警告

-(void) optionalFunction

{

    NSLog(@"OptionalFunction PS: 我是protocol中得可选协议,不实现我,不会有警告!");

}

@end

?    ?    测试的运行结果为:


1

2

2014-08-05 17:38:50.189 Memory[1907:303] RequiredFunction PS: 我是协议中required方法,不实现我会有警告!

2014-08-05 17:38:50.190 Memory[1907:303] OptionalFunction PS: 我是protocol中得可选协议,不实现我,不会有警告!

?    ?在声明对象的时候引入协议可以类比这Java中得泛型来学习, 例如声明一个遵守FirstProtocol协议的对象: id<FirstProtocol> obj;下面我们将用一个事例来介绍具体的用法

?    ?    ?1.创建一个CalculatorProtocol的协议,在协议中声明一个calculatorFunction的方法来进行两个数的计算,文件名为:calculatorProtocol.h

?    ?    ?    ?代码如下: ?    ?


1

2

3

4

5

#import <Foundation/Foundation.h>

//声明计算方法

@protocol CalculatorProtocol <NSObject>

-(void)calculatorFunction : (int) x  withY : (int) y;

@end

?    ?

?      2.在CalculatorClass类中添加新的方法,在这个类中有一个计算方法,需要对两个数的计算,有一个参数是对象类型的必须遵循协议CalculatorProtocol,主要代码如下:


1

2

3

4

5

6

7

//实现传入的对象必须服从协议的方法

-(void) calculatorFunction:(int)x

                     withY:(int)y

                   withObj:(id<CalculatorProtocol>)obj

{

    [obj calculatorFunction:x withY:y];

}

?    ?   3.定义遵循协议calculatorProtocol的类AddClass,在AddClass中实现calculatorFunction方法,实现两个数相加的功能代码如下


1

2

3

4

5

6

7

8

9

10

11

#import "AddClass.h"

@implementation AddClass

//实现CalculatorProtocol必须的方法

-(void)calculatorFunction:(int)x withY:(int)y

{

    int a = x + y;

    NSLog(@"AddClass PS: 我是实现协议的加方法%d + %d = %d", x, y, a);

}

@end

?      4.新建一个DecClass类,同样遵循calculatorProtocol协议,实现两个数相减的功能,主要代码如下:


1

2

3

4

5

6

7

8

9

10

#import "DecClass.h"

@implementation DecClass

//实现protocol中必须实现的方法

-(void) calculatorFunction:(int)x withY:(int)y

{

    int a = x - y;

    NSLog(@"DecClass PS: 我是重写的减方法%d - %d = %d", x, y, a);

}

@end

 

?测试代码:


1

2

3

4

5

6

7

//测试协议对象

AddClass *add = [AddClass new];

//往protocol对象中的calculator方法中传入符合协议的add对象

[pro calculatorFunction:2 withY:2 withObj:add];

DecClass *dec = [DecClass new];

[pro calculatorFunction:4 withY:3 withObj:dec];

?运行结果如下:


1

2

2014-08-05 17:38:50.190 Memory[1907:303] AddClass PS: 我是实现协议的加方法2 + 2 = 4

2014-08-05 17:38:50.191 Memory[1907:303] DecClass PS: 我是重写的减方法4 - 3 = 1

?

  再举一个理解协议更好理解协议的例子吧,我们声明一个文件协议,协议的内容是对文件的读和写。我们在声明一个文件管理系统的类,只要是文件能读和写就能放进我们的文件管理系统进行管理。

  1.指定可放入文件管理系统文件需要遵循的协议,协议中规定文件必须有读写的功能

  代码如下

#import <Foundation/Foundation.h>

@protocol FileManagerProtocol <NSObject>
//读方法
-(void) read;
//写方法
-(void) writer;
@end

  

  2.编写文件管理系统,来对所有遵守协议的文件来进行的统一的管理

  代码如下:

  声明:

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

@interface FileManagerSystem : NSObject
-(void) insertFileSystem: (id<FileManagerProtocol>) file;
@end

  实现:

#import "FileManagerSystem.h"

@implementation FileManagerSystem
-(void)insertFileSystem:(id<FileManagerProtocol>)file
{
    [file read];
    [file writer];
}

@end

  3.定义新的文件类来遵守我们的文件读写协议,之后就可以放入到我们的管理系统中进行管理

  文件类1

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

@interface File : NSObject<FileManagerProtocol>
@property (nonatomic,strong) NSString *fileName;
@end

#import "File.h"
@implementation File
//实现协议中的方法
-(void)read
{
    NSLog(@"我是文件%@,你可以对我进行阅读",_fileName);
}

-(void)writer
{
    NSLog(@"我是文件%@,你可以对我进行修改",_fileName);
}

@end

  

  在定义一个简历文件,同样遵守我们的文件协议

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

@interface JianLi : NSObject<FileManagerProtocol>
@property (nonatomic, strong) NSString *fileName;
@end

#import "JianLi.h"

@implementation JianLi
-(void)read
{
    NSLog(@"对简历%@的读", _fileName);
}
-(void)writer
{
    NSLog(@"对简历%@的写", _fileName);
}

@end

  然后我们可以把各种不同文件但都遵循我们文件协议的文件放入到我们的文件管理系统进行管理

 1     //声明文件,然后放入文件管理系统
 2     File *file = [File new];
 3     file.fileName = @"浪潮之巅";
 4
 5     //实例化文件二,只要符合文件协议即可
 6     File *file1 = [File new];
 7     file1.fileName = @"file1";
 8
 9     JianLi *jianLi = [JianLi new];
10     jianLi.fileName = @"lusashi的简历";
11
12     //实例化文件管理系统
13     FileManagerSystem *fileSystem = [FileManagerSystem new];
14
15
16
17     //把书加入到管理系统中
18     [fileSystem insertFileSystem:file];
19     [fileSystem insertFileSystem:file1];
20     [fileSystem insertFileSystem:jianLi];

  运行结果:

1 2014-08-14 12:05:47.956 Memory[985:303] 我是文件浪潮之巅,你可以对我进行阅读
2 2014-08-14 12:05:47.958 Memory[985:303] 我是文件浪潮之巅,你可以对我进行修改
3 2014-08-14 12:05:47.958 Memory[985:303] 我是文件file1,你可以对我进行阅读
4 2014-08-14 12:05:47.959 Memory[985:303] 我是文件file1,你可以对我进行修改
5 2014-08-14 12:05:47.959 Memory[985:303] 对简历lusashi的简历的读
6 2014-08-14 12:05:47.959 Memory[985:303] 对简历lusashi的简历的写
时间: 2024-11-08 18:57:39

Objective-C中的类目,延展,协议的相关文章

类目 延展 协议

1.类目 类目就是为已存在的类添加新的方法.但是不能添加实例变量.比如系统的类,我们看不到他的.m文件,所以没有办法用直接添加方法的方式去实现. 首先先建个类目 command+n 给什么类写类目下面就写那个类的名字 上面填的是给这个类添加的方法的名字 @interface NSMutableArray (Sort) //为NSMutableArray类添加Sort方法,Sort就是类目名,做到见名知意-(void)invert;//方法@end 实现部分 #import "NSMutableA

OC -- 类的类目 , 延展 , 协议

类目 分两部分: 1.系统已经写好的类目:按照功能对系统的类方法进行区分. 类目从@interface开始,后面是当前类名字,类名后是分类的功能, 到@end结束. 2.我们创建的类目,一般是为了把系统的类进行扩充. 对系统的类(例:NSString)添加文件Objective-C File {File:StringMethod; File Type:Category; Class: NSString}后,会自动出现@interface NSString (StringMethod).文件名为:

[objective-c] 03 - 类目 延展 协议

本章主要讲解OC语言特性 类目(Category) 延展(Extension) 协议(Protocol) 1.类目 OC语言中的类目机制只有一个作用:为任何一个类添加方法 现在我们创建一个Student类 @interface Student : NSObject @property(nonatomic,strong)NSString * name; @end @implementation @end 如果想为Student类添加一个方法,现在有两种方法 直接修改Student类的源码,声明一个

类目,延展,协议的基本概念

Catgory(类目/分类) 1.分类是给原有类添加方法,它只能添加方法,不能添加属性(成员变量) 2.分类中定义@property,只会生成setter/getter方法的声明,没有方法的实现以及私有变量. 3.分类中的方法不能和本类的方法名相同,否则会有警告,而且调用的时候会优先调用分类的方法,即覆盖本类的方法. 4.分类的方法和实现分开,一对多,1个.h文件对应多个.m文件,典型的分散实现: 延展(Extension) 1.延展为类创建私有方法,一个.m文件对应多个.h文件,分配权限时可以

Objective-C中的类目与协议

类目的定义与类的定义相似: 1.声明 @interface NSString (CSayHi)       NSString是目标类:CSayHi是类目名称: 且后面没有 :NSObject 2.实现 @implementation NSString (CSayHi) 3.文件名 NSString+CSayHi 类目: 类目也成为分类(特征) 1.可以为已知的类添加方法,哪怕是你没有源代码的类: 2.通过类目添加方法会成为原始类的一部分: 3.与原类中的方法同级: 4.而且会被子类继承: 类目的

【objective-c】类目 延展 协议

1.类目 类目就是为已存在的类添加新的方法.但是不能添加实例变量.比如系统的类,我们看不到他的.m文件,所以没有办法用直接添加方法的方式去实现. Category的使用场景有那些呢:1.类包含了很多个方法实现,而这些方法需要不同团队的成员来实现2.当你在使用基础类库中的类时,你不想继承这些类而只想添加一些方法时. Category能实现上面的需求,当然也有使用Category是需要注意的问题: 1.Category可以访问原始类的实例变量,但不能添加实例变量,如果想添加变量,那就通过继承创建子类

Objective-C类目延展协议

一.类目:(Category) 是在原有类的基础之上添加方法,在使用的时候只需要用原有类实例化出来的对象即可: 实际开发中什么情况下使用类目? 已经封装好的类,(不希望再改变原有类) 团队里面分工开发一个模块的时候可以使用自己定义的方法: 二.延展:(Extension)的基本概念和用法: 在xcode4.3之前直接使用self 调用方法  那时候会报错,所以的用延展 就是在类中添加私有方法,延展中声明的方法在类的本身的@interface  类名()和它对应的@end之间实现: 类有时需要方法

Objective-C中的类目(Category),延展(Extension)

类目和延展的作用都是为了扩展一个类. Objective-C中的类目(Category) 一.类目的定义和作用 类目也叫分类,英文Category,在没有原类.m文件的基础上,给该类添加方法. 比如,NSString类原本没有helloString方法,我们又没有NSString类的原代码,那我们想给NSString类添加一个helloString的方法,只有通过声明子类或者类目才可以达到这个目的. 二.类目的声明: @interfaceNSString (hello) - (void)hell

OC-类目延展协议

类目(Category) 延展(Extension) 协议(Protocol) 一.类目 OC语言中的类目机制只有一个作用:为任何一个类添加方法 注意: 1.不能在分类中添加属性,只能添加方法 2.如果再分类里面使用@property,那么它只能生成getter和setter的声明,没有实现 3.如在在分类中写了与本类同名的方法,优先调用分类里面的方法,所以在分类中定义类的时候,尽量避免和本类中的方法重名 4.在分类里面可以访问本类里面所定义的属性 我们为NSString类添加一个方法,实现字符