篇文章里我们来聊聊如何扩展一个类的方法和实例变量,我们首先来看一下命名分类如何扩展一个类。在下面的代码中,首先定义一个类Player用来定义普通球员,如果第三方开发者发现普通球员缺少了一些方法,则可以用分类ext来扩充喽:

:默认的Player类

Player.h文件:

#import<Foundation/Foundation.h>

@interfacePlayer:NSObject{
intnumber;
intage;
}
-(void)show;
-(id)init:(int)n:(int)age;
@end

Player.m文件:

#import"Player.h"

@implementationPlayer
-(id)init:(int)n:(int)age_v{
self= [super init];
if(self){
number= n;
age= age_v;
}
returnself;
}

-(void)show{
NSLog(@"playerx ,number:%d,age:%d",number,age);
}
@end

test.m文件:

#import"Player.h"

intmain(int argc,char **argv)
{
@autoreleasepool{
Player*p = [[Player alloc] init: 1 :20];

[pshow];
}
return0;
}

编译执行结果如下:

apple@kissAir:Player$clang -fobjc-arc -framework Foundation
Player.m test.m -o main

apple@kissAir:Player$./main

2014-06-3017:55:56.053 main[3862:507] player
x ,number:1,age:20

现在一个第三方软件公司觉得球员球员太不活泼,so他们决定给球员添加方法say和train:

Player_ext.h文件

#import"Player.h"

@interfacePlayer (ext)
//@propertyint power;

//-(id)init:(int)n:(int)age :(int)power;
-(void)say;
-(void)train;
@end

Player_ext.m文件

#import"Player_ext.h"

@implementationPlayer (ext)
//@synthesizepower;

/*
-(id)init:(int)n :(int)age_v :(int)pow{
self= [super init :n :age_v];
if(self){
power= pow;
}
returnself;
}
*/

-(void)say{
NSLog(@"player[n:%d]want to say : hello!",number);
}

-(void)train{
NSLog(@"player[n:%d]is training...",number);
}
@end

test.m文件

//#import"Player.h"
#import"Player_ext.h"

intmain(int argc,char **argv)
{
@autoreleasepool{
Player*p = [[Player alloc] init: 1 :20];

[pshow];
[psay];
[ptrain];

}
return0;
}

我们编译运行看看结果咯:

apple@kissAir:Player$clang -fobjc-arc -framework Foundation
Player.m Player_ext.mtest.m -o main

apple@kissAir:Player$./main

2014-06-3018:16:09.050 main[4246:507] player
x ,number:1,age:20

2014-06-3018:16:09.052 main[4246:507] player[n:1]
want to say : hello!

2014-06-3018:16:09.053 main[4246:507] player[n:1]
is training...

我们发现在命名分类中试图添加实例变量是不允许的,只能在未命名分类中添加,而且未命名分类中声明方法的实现只能放在主类的实现中。下面修改代码,增加power属性,并且train动作是要耗费power的,遂修改该方法,同时新增init方法如下:

@implementation Player (ext)
	//@synthesize power;

/*
	-(id)init :(int)n :(int)age_v :(int)pow{
		self = [super init :n :age_v];
		if(self){
			power = pow;
		}
		return self;
	}
*/

	-(void)say{
		NSLog(@"player[n:%d] want to say : hello!",number);
	}

	-(void)train{
		NSLog(@"player[n:%d:pow:%d] is training...power is down to %d",\
			number,self.power,self.power -= 10);
	}

Player.h文件

#import <Foundation/Foundation.h>

@interface Player:NSObject{
	int number;
	int age;
}
	-(void)show;
	-(id)init:(int)n :(int)age;
@end

@interface Player ()
	@property int power;

	-(id)init :(int)n :(int)age :(int)power;
@end

Player.m文件

#import "Player.h"

@implementation Player
	@synthesize power;

	-(id)init:(int)n :(int)age_v{
		self = [super init];
		if(self){
			number = n;
			age = age_v;
		}
		return self;
	}

	-(id)init :(int)n :(int)age_v :(int)pow{
		self = [super init];
		if(self){
			self = [self init :n :age_v];
			power = pow;
		}
		return self;
	}

	-(void)show{
		NSLog(@"player x ,number:%d,age:%d,power:%d",number,age,power);
	}
@end

test.m文件

#import "Player_ext.h"

int main(int argc,char **argv)
{
	@autoreleasepool{
		Player *p = [[Player alloc] init: 1 :20 :100];

		[p show];
		[p say];
		[p train];
		[p show];

	}
	return 0;
}

编译运行结果如下:

apple@kissAir: Player$clang -fobjc-arc -framework Foundation Player.m Player_ext.m test.m -o main

apple@kissAir: Player$./main

2014-06-30 18:52:29.237 main[4822:507] player x ,number:1,age:20,power:100

2014-06-30 18:52:29.239 main[4822:507] player[n:1] want to say : hello!

2014-06-30 18:52:29.240 main[4822:507] player[n:1:pow:100] is training...power is down to 90

2014-06-30 18:52:29.240 main[4822:507] player x ,number:1,age:20,power:90

有球员就有教练啊,现在添加教练类。教练类和球员类有共性的地方哦,就是都有say和train方法。这个共性的地方不妨就用协议来描述吧,需要说明的是教练还有一个召开发布会方法,该方法球员是没有的,我们把它作为一个可选方法放入协议。为了方便就把教练类放在test.m中喽:

Player.h文件

#import <Foundation/Foundation.h>

@protocol Actions
	-(void)say;	//必须存在
@optional
	-(void)convoke;  //可选方法
@required
	-(void)train; //必须存在
@end

@interface Player:NSObject{
	int number;
	int age;
}
	-(void)show;
	-(id)init:(int)n :(int)age;
@end

@interface Player ()
	@property int power;

	-(id)init :(int)n :(int)age :(int)power;
@end

Player_ext.h文件

#import "Player.h"

@interface Player (ext) <Actions>
	//@property int power;

	//-(id)init:(int)n :(int)age :(int)power;
	-(void)say;
	-(void)train;
@end

test.m文件

//#import "Player.h"
#import "Player_ext.h"

@interface Coach:NSObject <Actions>

@end

@implementation Coach
	-(void)say{
		NSLog(@"coach say : hello!");
	}

	-(void)train{
		NSLog(@"coach is leading train...");
	}

	-(void)convoke{
		NSLog(@"coach is convoking a meeting...");
	}
@end

int main(int argc,char **argv)
{
	@autoreleasepool{
		Player *p = [[Player alloc] init: 1 :20 :100];
		Coach *c = [[Coach alloc] init];

		[p show];
		[c say];
		[c convoke];
		[c train];
		[p say];
		[p train];
		[p show];

	}
	return 0;
}

编译运行结果如下:

apple@kissAir: Player$./main

2014-06-30 20:33:24.930 main[6466:507] player x ,number:1,age:20,power:100

2014-06-30 20:33:24.932 main[6466:507] coach say : hello!

2014-06-30 20:33:24.933 main[6466:507] coach is convoking a meeting...

2014-06-30 20:33:24.933 main[6466:507] coach is leading train...

2014-06-30 20:33:24.934 main[6466:507] player[n:1] want to say : hello!

2014-06-30 20:33:24.934 main[6466:507] player[n:1:pow:100] is training...power is down to 90

2014-06-30 20:33:24.934 main[6466:507] player x ,number:1,age:20,power:90

如果要添加多个协议语法为: @interface A <p_a,p_b>

最后我们可以用反射方法测试类是否遵守协议:

Protocol *actions = @protocol(Actions);
		Player *p = [[Player alloc] init: 1 :20 :100];
		Coach *c = [[Coach alloc] init];

		if([p conformsToProtocol: actions]){
			NSLog(@"Player abide protocol Actions"); //Coach同样遵守
		}

		//对于可选方法我们可以用一般的respondsToSelector方法来测试:
		if([c respondsToSelector :@selector(convoke)]){
			NSLog(@"Coach has convoke method");
		}

obj-c编程08:分类和协议的更多相关文章

  1. 嵌入式linux的网络编程(1)--TCP/IP协议概述

    嵌入式linux的网络编程(1)--TCP/IP协议概述 1.OSI参考模型及TCP/IP参考模型 通信协议用于协调不同网络设备之间的信息交换,它们建立了设备之间互相识别的信息机制.大家一定都听说过著 ...

  2. 老雷socket编程之认识常用协议

    老雷socket编程之常见网络协议 1.ip IP协议是将多个包交换网络连接起来,它在源地址和目的地址之间传送一种称之为数据包的东西, 它还提供对数据大小的重新组装功能,以适应不同网络对包大小的要求. ...

  3. Day09: socket网络编程-OSI七层协议,tcp/udp套接字,tcp粘包问题,socketserver

    今日内容:socket网络编程    1.OSI七层协议    2.基于tcp协议的套接字通信    3.模拟ssh远程执行命令    4.tcp的粘包问题及解决方案    5.基于udp协议的套接字 ...

  4. 04OC之分类Category,协议Protocol,Copy,代码块block

    一.Protocol协议 我们都知道,在C#有个规范称之为接口,就是规范一系列的行为,事物.在C#中是使用Interface关键字来声明一个接口的,但是在OC中interface是用来声明类,所以用了 ...

  5. 【Objective-C 基础】4.分类和协议

    1.分类 OC提供了一种与众不同的方式--Category,可以动态的为已经存在的类添加新的行为(方法) 这样可以保证类的原始设计规模较小,功能增加时再逐步扩展. 使用Category对类进行扩展时, ...

  6. python 之 网络编程(基于TCP协议的套接字通信操作)

    第八章网络编程 8.1 基于TCP协议的套接字通信 服务端套接字函数 s.bind() 绑定(主机,端口号)到套接字 s.listen() 开始TCP监听 s.accept() 被动接受TCP客户的连 ...

  7. 网络编程——基于TCP协议的Socket编程,基于UDP协议的Socket编程

    Socket编程 目前较为流行的网络编程模型是客户机/服务器通信模式 客户进程向服务器进程发出要求某种服务的请求,服务器进程响应该请求.如图所示,通常,一个服务器进程会同时为多个客户端进程服务,图中服 ...

  8. Objective-C语言分类与协议

    分类(Category)允许向一个类文件中添加新的方法声明,它不需要使用子类机制,并且在类实现的文件中的同一个名字下定义这些方法.其语法举例如下: #import "ClassName.h& ...

  9. iOS开发笔记系列-基础5(分类和协议)

    分类 在Objective-C中,除了通过新建子类的方式来向类添加新方法外,还可以通过分类的方式.分类提供了一种简单的方式,将类的定义模块化到相关方法的组或分类中,它还提供了扩展现有类定义的简便方式, ...

随机推荐

  1. 4.QPixmap,QTransform,绘图函数的使用

     新建一个项目Painter MyWidget.h #ifndef MYWIDGET_H #define MYWIDGET_H #include <QWidget> class MyW ...

  2. 编译GDAL支持ArcObjects

    编译GDAL支持ArcObjects. 首先修改nmake.opt文件中对应的ArcObjects,修改后的如下所示: #uncomment to use ArcObjects ARCOBJECTS_ ...

  3. Struts2配置问题终极解决方案

    从下午忙到现在,终于找到问题的根源了.写下此文,与君共勉. 我的目录结构是这样的. 关于配置文件加载问题 控制台下面报错,提示错误信息如下: 严重: Exception starting filter ...

  4. iOS下WebRTC音视频通话(二)-局域网内音视频通话

    这里是iOS 下WebRTC音视频通话开发的第二篇,在这一篇会利用一个局域网内音视频通话的例子介绍WebRTC中常用的API. 如果你下载并编译完成之后,会看到一个iOS 版的WebRTC Demo. ...

  5. 文件夹或者文件比对工具 Beyond Compare

    文件夹或者文件比对工具 Beyond Compare 之前有同事离职了.       没有工作交接.       同事的代码有一部分也没有提交版本库.       结果就是线上的代码和版本库中的文件数 ...

  6. Android进阶(五)在Eclipse中关联Gson源码

    1)获得相应的jar包gson-2.2.4-sources.jar与gson-2.2.4-javadoc.jar. 2)在libs目录下新建src包和docs包,将相应jar包放入相应文件夹内. 3) ...

  7. Java 8时间和日期API 20例

    本文由 ImportNew - Sandy 翻译自 javarevisited.欢迎加入翻译小组.转载请见文末要求. 伴随lambda表达式.streams以及一系列小优化,Java 8 推出了全新的 ...

  8. 一个CSS+jQuery的放大缩小动画效果

    日期: 2013年9月23日 作者:铁锚 // 今天帮朋友写了一些代码,自己觉得写着写着,好几个版本以后,有点满意,于是就贴出来. // 都是定死了的.因为需求就只有4个元素.如果是要用CSS的cla ...

  9. 分布式进阶(九)Ubuntu下使用nsenter进入Docker容器

    使用nsenter进入Docker容器 Docker容器运行后,如何进入容器进行操作呢?起初我是用SSH.如果只启动一个容器,用SSH还能应付,只需要将容器的22端口映射到本机的一个端口即可.当我启动 ...

  10. Oracle Forms Services Architecture

    Oracle Forms Services Architecture Author:                         PTIAN(tianpan@gmail.com) Creation ...