在编写面向对象程序的时候,我们经常想为现有的类添加一些新的行为。有些时候,我们可以创建这个类的子类。但是,如果我们用到工具集或者类库的时候,无法处理新建的子类。这时,Objective-C就给我们提供了一个非常方便好用的方式 —— 类别(category)。

  那么,什么是类别呢?类别是一种为现有的类添加新方法的方式。你只需要知道这个类的公开接口,不需要知道类的源代码。而且可以将类定义模块化地分布到多个相关文件中。

  类别同样由声明部分和实现部分组成,声明部分语法格式如下:

 @interface 已经存在的类名 (类别名)
// 方法定义
...
@end

  类别实现部分的语法格式如下:

 @implmentation 已经存在的类名 (类别名)
// 实现方法代码
...
@end

  类别是Objective-C中一个非常重要的知识,它通常有如下3种用法:

1). 利用类别对类进行模块化设计;
2). 使用类别来调用私有方法;
3). 使用类别来实现非正式协议。

  下面,我们通过一个例子,给大家展示下如何来使用类别这个方式。就编程习惯而言,一般习惯将类别的接口文件名命名为“类名+类别名.h”的形式,实现部分文件则命名为“类名+类别名.m”。

  首先,我们创建一个名为:NSNumber+Calculate的类文件。创建好类文件,项目中会自动生成两个文件:

  接下来,我们就分别来写接口文件和实现文件的代码。

 //
// NSNumber+Calculate.h
// #import <Foundation/Foundation.h> @interface NSNumber(Calculate)
// 在类别中定义了4个方法
-(NSNumber*) add: (double) num2;
-(NSNumber*) substract: (double) num2;
-(NSNumber*) multiply: (double) num2;
-(NSNumber*) divide: (double) num2;
@end

  实现部分代码:

 //
// NSNumber+Calculate.m
// #import "NSNumber+Calculate.h" @implementation NSNumber(Calculate)
// 实现类别的接口部分定义的4个方法
-(NSNumber*) add: (double) num2
{
return [NSNumber numberWithDouble:([self doubleValue] + num2)];
}
-(NSNumber*) substract:(double)num2
{
return [NSNumber numberWithDouble:([self doubleValue] - num2)];
}
-(NSNumber*) multiply: (double) num2
{
return [NSNumber numberWithDouble:([self doubleValue] * num2)];
}
-(NSNumber*) divide: (double) num2
{
return [NSNumber numberWithDouble:([self doubleValue] / num2)];
}
@end

  最后,在main主函数中调用定义的方法,来测试下我们定义的类别方法是否能正常实现。

 //
// main.m
// #import <Foundation/Foundation.h>
#import "NSNumber+Calculate.h" int main(int argc, const char * argv[])
{ @autoreleasepool {
NSNumber* myNum = [NSNumber numberWithInt:];
// 测试 add方法
NSNumber* add = [myNum add:2.4];
NSLog(@"Add: %@", add);
// 测试 substract方法
NSNumber* substract = [myNum substract:2.4];
NSLog(@"Add: %@", substract);
// 测试 multiply方法
NSNumber* multiply = [myNum multiply:2.4];
NSLog(@"Add: %@", multiply);
// 测试 divide方法
NSNumber* divide = [myNum divide:2.4];
NSLog(@"Add: %@", divide);
}
return ;
}

  正常运行后的结果如下:

  虽然类别可以重写原有类中的方法,但通常不推荐这么做。如果需要重写原类的方法,更好的建议是通过原有类的派生类,然后再子类中重写父类的原有方法来实现。

  通过类别为指定类添加新方法之后,这个新方法不仅会影响NSNumber类,还会影响NSNumber类的所有子类,每个子类都会获取类别扩展的方法。同时,可以根据需要,为一个类定义多个类别,不同的类别都可以对原有的类添加方法定义。

  好了,类别的概念和基本的使用方法就介绍这么多。下一篇博文,我们将介绍另外几个在Objective-C中非常重要的:协议和委托。

《objective-c基础教程》学习笔记(十一)—— 类别的更多相关文章

  1. Python基础教程学习笔记:第一章 基础知识

    Python基础教程 第二版 学习笔记 1.python的每一个语句的后面可以添加分号也可以不添加分号:在一行有多条语句的时候,必须使用分号加以区分 2.查看Python版本号,在Dos窗口中输入“p ...

  2. 【学习笔记】Python基础教程学习笔记

    教程视频网盘共享:http://pan.baidu.com/s/1hrTrR5E 03-python基础.if判断 print 输出数据 print("hahahah")----- ...

  3. Objective-C基础教程学习笔记(附录)从Java转向Objective-C

    Java接口与Objective- C正式协议类似,因为它们都需要实现一组方法.Java具有抽象类,但Objective-C没有.Java具有类变量,但在Objective-C中, 可以使用文件范围内 ...

  4. 匿名内部类--毕向东java基础教程学习笔记

    1.匿名内部类其实就是内部类的简写形式. 2.定义匿名内部类的前提: 该内部类必须继承一个类,或者实现一个接口. 3.匿名内部类的格式:new 父类名或接口名(){定义子类内容:} 4.其实匿名内部类 ...

  5. 内部类--毕向东Java基础教程学习笔记

    内部类的访问规则 1. 内部类可以直接访问外部类的成员,包括私有. 之所以可以直接访问外部类的成员,是因为内部类中持有外部类的引用,格式:外部类名.this 2.外部类要访问内部类,必须建立内部类对象 ...

  6. 异常处理——毕向东Java基础教程学习笔记

    1.异常:就是程序运行过程中出现的不正常情况. 异常的由来:问题本身也是日常生活中一个具体的事物,也可以通过java类的形式进行描述,并封装成对象.                        其实 ...

  7. 《嵌入式Linux基础教程学习笔记一》

    常用书目下载地址:http://www.cnblogs.com/pengdonglin137/p/3688029.html 第二章 1.进程上下文和中断上下文(Page20) 当应用程序执行系统调用, ...

  8. Python基础教程学习笔记:第二章 列表和元组

    1.序列中元素的索引: 第一个元素索引是0,第二个是1,依次递增 最后一个元素索引是-1,倒数第二个是-2,依次递减 2.序列(Sequence)的种类: 列表(list).元组(tuple).字符串 ...

  9. objective-c基础教程——学习小结

    objective-c基础教程——学习小结   提纲: 简介 与C语言相比要注意的地方 objective-c高级特性 开发工具介绍(cocoa 工具包的功能,框架,源文件组织:XCode使用介绍) ...

  10. Objective-c基础知识学习笔记

    Objective-c基础知识学习笔记(一) 一直有记录笔记的习惯.但非常久没分享一些东西了,正好上半年開始学习IOS了,如今有空写点.因开发须要,公司特意为我们配置了几台新MAC.还让我们自学了2周 ...

随机推荐

  1. I535卡刷土豆修改4.1.2版本ROMV4過程

    I535卡刷土豆修改版本ROMV4過程 一.首先在电脑上安装I535的电脑驱动程序 二.備份EFS,備份舊ROM(网上有教程) 三.解锁:下载EZ-Unlock解锁. 四.檢查Recovery是否為最 ...

  2. linux基本命令--学习记录

    1.mkdir -p 递归创建目录(-p参数代表递归创建): 2.touch 创建file: 3.cat 查看 5.vi 编辑器 6.echo >(直接覆盖) 或者<<(后面追加)单 ...

  3. WPF学习开发客户端软件-任务助手(已上传源码)

    本人纯属WPF新手,布局和WPF的开发水平相当欠缺,从个人来说,还是比较喜欢WPF的,有人说WPF是界面加上WINFORM,我不这样认为,WPF与WINFORM主要的不同在于数据绑定.   这个软件虽 ...

  4. 深入浅出话VC++(3)——VC++实现绘图操作

    VC++实现绘图操作,说白了也就是对API熟练操作了,下面介绍几种绘图 1. 绘制线条 具体实现代码如下: // 鼠标左键按下时的处理函数 void CDrawView::OnLButtonDown( ...

  5. HttpClient读取ASP.NET Web API错误信息的简单方法

    在C#中,用HttpClient调用Web API并且通过Content.ReadAsStringAsync()读取响应内容时,如果出现500错误(InternalServerError),会得到一个 ...

  6. [MSSQL]如何高效查询表的总记录数

    如何高效查询表的总记录数?[总结-整理-马克] 首先想到的自然是在表主键上应用COUNT函数来查询了,这个是目前使用最多的方法,没有之一 ) ROWS FROM product 这里再给出一些其它方法 ...

  7. Sale.js——快速创建促销样式

    小菜编写的又一款jQuery小插件,有兴趣的朋友可以试试~ 简介: 对于一个用于产品展示.销售的网站而言,很可能需要一种促销的特效. 一般而言,我们会在商品图片前加一个促销栏,写上一些促销标语.原价. ...

  8. 云端持续集成——AppVeyor拥抱GitHub

    想着你正在做一个网站 终于大功告成了,提交了代码后,你按下了开发环境的Build菜单,一杯咖啡后,Build Succeed,然后连接服务器,开始部署 当你乐滋滋的享受着你的开发成果时,突然发现了一个 ...

  9. JQuery文本框水印插件的简单实现

    采用JQuery实现文本框的水印效果非常容易,效果如下: 代码片段,定义要应用水印效果的文本框的样式: .watermark { color: #cccccc; } 将JavaScript代码封装成J ...

  10. Oracle基础表空间建立,以及练习

    Oracle的表空间创建,可以采用网页的https://127.0.0.1:1158/em来进入oracle的页面进行创建表空间. 利用plsqldev.exe程序在表空间里添加数据: 首先要在use ...