Objective-c---分类 、 扩展 、 ARC
1 分类练习
1.1 问题
分类是Objective-C提供的一种类的补充和扩展方法,补充和扩展的每个部分被称为分类,分类本质上是类的一部分。提出分类概念的作用有两个:一是分解大的代码,提高程序可读性;另一个是给已有的类添加新方法。
1.2 方案
定义一个TRMyClass类,在类中包含一个属性property,用于存储一个整型数,同时定义一个方法method1,该方法在控制台输出“method1执行了”。
首先,为TRMyClass类定义一个分类AddMethod,在分类中添加一个方法method2,该方法在控制台输出“method2执行了”。
然后,为TRMyClass类定义一个扩展。在扩展中定义一个私有实例变量age,用于存储一个整型的年龄,再定义一个私有属性sex,用于存储一个字符型的性别,同时定义一个私有方法addMethod,该方法在控制台输出“method执行了”。
下一步,为NSString类定义一个分类TRConnectionServer,在分类中添加一个方法connection,该方法在控制台输出“连接服务器中……”。
最后,在主程序中,使用分类。
1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义类TRMyClass
首先在Day05工程中添加TRMyClass.h文件,用于定义类TRMyClass。
代码如下所示:
- #import <Foundation/Foundation.h>
- @interface TRMyClass : NSObject
- @property(nonatomic,assign)int property;
- -(void)method1;
- @end
上述代码中,以下代码:
- @property(nonatomic,assign)int property;
定义了一个属性,用于存储一个整型变量。它有两个参数,一个是nonatomic,它代表对属性赋值的时候不加锁,即在多线程环境下访问时可能会出现数据错误,如果需要在多线程环境下运行,为保证数据不会出现错误,可使用atomic参数,它会在对属性赋值的时候加锁。另一个参数是assign,对于C语言的基本数据类型,只能选取这个参数。
上述代码中,以下代码:
- -(void)method1;
定义了一个方法,该方法只是为了说明分类概念而定义的,所以没有任何实际意义,只是在函数体中输出一行提示。
然后,在类TRMyClass的实现部分,将类中声明的方法进行实现。类TRMyClass的实现部分存放于Day05工程新添加的TRMyClass.m文件中。
代码如下所示:
- #import "TRMyClass.h"
- @implementation TRMyClass
- -(void)method1{
- NSLog(@"method1执行了");
- }
- @end
步骤二:定义分类AddMethod
在Day05工程中添加TRMyClass类的AddMethod分类的方法是:在工程导航窗口中,用鼠标指向Day05文件夹,并单击鼠标右键,显示一个菜单,如图-1所示:
图-1
如图-1,选择“New File…”菜单项,打开新文件模板窗口。在该窗口中,选择OS X下的Cocoa,并在右侧选择“Objective-C category”,如图-2所示:
图-2
单击Next按钮,进入选择对话框,如图-3所示:
图-3
在图-3中,Category分类名文本框中填入分类名AddMethod;Category on分类属于下拉框中选择TRMyClass。然后单击Next按钮,选择AddMethod分类文件存储地址,如图-4所示:
图-4
此时,一般直接按按钮Create即可。此时将返回工程窗口,在工程导航中,可以见到新生成的TRMyClass+AddMethod分类的两个文件。注意,此时生成的分类文件名由两部分组成,即分类所属的类名+分类名。如图-5所示:
图-5
至此,AddMethod分类创建完毕。
步骤三:在AddMethod分类中添加方法
首先,在分类AddMethod的声明中,即在TRMyClass+AddMethod.h文件中,添加method2方法的声明。
代码如下所示:
- #import "TRMyClass.h"
- @interface TRMyClass (AddMethod)
- {
- //int age;分类中不可以创建实例变量
- }
- -(void)method2;
- @end
注意:在分类中不能创建新的实例变量,只能添加新的方法。
然后,在分类AddMethod的实现部分,即在TRMyClass+AddMethod.m文件中,添加method2方法的实现。
代码如下所示:
- #import "TRMyClass+AddMethod.h"
- @implementation TRMyClass (AddMethod)
- -(void)method2{
- self.property = 18;
- NSLog(@"添加了method2方法");
- }
- @end
上述代码中,以下代码:
- -(void)method2{
- self.property = 18;
- NSLog(@"添加了method2方法");
- }
在方法method2中可以访问分类AddMethod所属的主类TRMyClass中的属性property,将其赋值为18。
步骤四:在主程序中使用分类
首先在Day05工程的main.m文件中添加代码。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "TRMyClass.h"
- #import "TRMyClass+AddMethod.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- TRMyClass* myClass = [[TRMyClass alloc]init];
- [myClass method1];
- [myClass method2];
- }
- return 0;
- }
上述代码中,以下代码:
- TRMyClass* myClass = [[TRMyClass alloc]init];
定义TRMyClass类的对象myClass。
上述代码中,以下代码:
- [myClass method1];
向对象myClass发送消息method1。方法method1声明和实现在TRMyClass类中,这和以前我们所学习的类方法的使用方法相同。
上述代码中,以下代码:
- [myClass method2];
向对象myClass发送消息method2。方法method2声明和实现在AddMethod分类中,在分类中声明和实现的方法,它的使用与分类所属的主类中的方法相同。在主程序中,只需要包含分类的头文件即可。因为分类是主类的一部分,所以只需要定义主类的对象,不需要再定义分类的对象。可以向主类的对象发送主类中声明和实现的方法,也可以向主类的对象发送分类中声明和实现的方法。
步骤五:定义扩展AddExtension
在Day05工程中添加TRMyClass类的AddExtension扩展的方法是:在工程导航窗口中,用鼠标指向Day05文件夹,并单击鼠标右键,显示一个菜单,如图-6所示:
图-6
如图-6,选择“New File…”菜单项,打开新文件模板窗口。在该窗口中,选择OS X下的Cocoa,并在右侧选择“Objective-C class extension”,如图-7所示:
图-7
单击Next按钮,进入选择对话框,如图-8所示:
图-8
在图-8中,Extension Name扩展名文本框中填入扩展名AddExtension;Class扩展属于下拉框中选择TRMyClass。然后单击Next按钮,选择AddExtension扩展文件存储地址,如图-9所示:
图-9
此时,一般直接按按钮Create即可。此时将返回工程窗口,在工程导航中,可以见到新生成的TRMyClass_AddExtension.h扩展头文件。注意,此时生成的扩展文件名由两部分组成,即分类所属的类名_扩展名。如图-10所示:
图-10
至此,AddExtension扩展创建完毕。
步骤六:在AddExtension扩展中添加私有属性和方法
首先,在扩展AddExtension的声明中添加一个实例变量age、一个属性sex和一个method2方法的声明。
代码如下所示:
- #import "TRMyClass.h"
- //扩展 延展 私有的内容
- @interface TRMyClass ()
- {
- int age;//私有的实例变量
- }
- @property(nonatomic,assign)char sex;//私有属性
- -(void)addMethod;//私有的方法
- @end
注意:在扩展中定义的实例变量、属性和方法都是私有的,只能被扩展所属的主类中的方法使用。
扩展除了按照上述方法被放在单独的.h文件中,还可以将其放在扩展所属的主文件的.m文件中。
代码如下所示:
- #import "TRMyClass.h"
- //扩展即可以放在.h文件中,也可以放在.m文件中
- //#import "TRMyClass_ADDExtention.h"
- //扩展 延展 私有的内容
- @interface TRMyClass ()
- {
- int age;//私有的实例变量
- }
- @property(nonatomic,assign)char sex;//私有属性
- -(void)addMethod;//私有的方法
- @end
- @implementation TRMyClass
- -(void)method1{
- NSLog(@"method1执行了");
- }
- -(void)addMethod{
- age = 100;
- self.sex = 'm';
- NSLog(@"method执行了");
- }
- @end
上述代码中,以下代码:
- -(void)addMethod{
- age = 100;
- self.sex = 'm';
- NSLog(@"method执行了");
- }
是在扩展所属的主文件的.m文件中实现方法的函数体。该方法在类外是不能被调用的,代码如下所示:
- #import <Foundation/Foundation.h>
- #import "TRMyClass.h"
- #import "TRMyClass+AddMethod.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- TRMyClass* myClass = [[TRMyClass alloc]init];
- [myClass method1];
- [myClass method2];
- //[myClass addMethod];//私有方法,不能调用
- }
- return 0;
- }
上述代码中,以下代码:
- //[myClass addMethod];//私有方法,不能调用
是在扩展所属的主类类外试图调用扩展中的方法addMethod,这样做编译是无法通过的。
步骤七:为NSString类定义一个分类TRConnectionServer
分类除了可以为自定义类添加外,还可以为没有源代码的第三方类或系统提供的类添加。例如,用步骤二中介绍的方法添加一个分类TRConnectionServer。
代码如下所示:
- #import <Foundation/Foundation.h>
- @interface NSString (TRConnectionServer)
- -(void)connection;
- @end
上述代码中,以下代码:
- @interface NSString (TRConnectionServer)
是为Objective-C提供的Foundation类库中的NSString类创建一个分类TRConnectionServer。
上述代码中,以下代码:
- -(void)connection;
是在分类TRConnectionServer中添加一个方法connection。
然后,在分类TRConnectionServer的实现部分,即在NSString+TRConnectionServer.m文件中,添加connection方法的实现。
代码如下所示:
- #import "NSString+TRConnectionServer.h"
- @implementation NSString (TRConnectionServer)
- -(void)connection{
- NSLog(@"连接服务器中...");
- }
- @end
步骤八:在主程序中使用分类TRConnectionServer
首先在Day05工程的main.m文件中添加代码。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "TRMyClass.h"
- #import "TRMyClass+AddMethod.h"
- #import "NSString+TRConnectionServer.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- TRMyClass* myClass = [[TRMyClass alloc]init];
- [myClass method1];
- [myClass method2];
- //[myClass addMethod];//私有方法,不能调用
- //可以给第三方或系统类添加能力
- NSString* str = [[NSString alloc]init];
- [str connection];
- }
- return 0;
- }
上述代码中,以下代码:
- //可以给第三方或系统类添加能力
- NSString* str = [[NSString alloc]init];
- [str connection];
可以直接创建一个NSString类的对象str,然后用该对象调用分类中定义的方法。
1.4 完整代码
本案例中,类TRMyClass声明,即TRMyClass.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- @interface TRMyClass : NSObject
- @property(nonatomic,assign)int property;
- -(void)method1;
- @end
类TRMyClass实现,即TRMyClass.m文件,完整代码如下所示:
- #import "TRMyClass.h"
- //扩展即可以放在.h文件中,也可以放在.m文件中
- //#import "TRMyClass_ADDExtention.h"
- //扩展 延展 私有的内容
- @interface TRMyClass ()
- {
- int age;//私有的实例变量
- }
- @property(nonatomic,assign)char sex;//私有属性
- -(void)addMethod;//私有的方法
- @end
- @implementation TRMyClass
- -(void)method1{
- NSLog(@"method1执行了");
- }
- -(void)addMethod{
- age = 100;
- self.sex = 'm';
- NSLog(@"method执行了");
- }
- @end
本案例中,分类AddMethod声明,即TRMyClass+AddMethod.h文件,完整代码如下所示:
- #import "TRMyClass.h"
- @interface TRMyClass (AddMethod)
- {
- //int age;分类中不可以创建实例变量
- }
- -(void)method2;
- @end
分类AddMethod实现,即TRMyClass+AddMethod.m文件,完整代码如下所示:
- #import "TRMyClass+AddMethod.h"
- @implementation TRMyClass (AddMethod)
- -(void)method2{
- self.property = 18;
- NSLog(@"添加了method2方法");
- }
- @end
本案例中,扩展AddExtention声明,即TRMyClass_AddExtention.h文件,完整代码如下所示:
- #import "TRMyClass.h"
- //扩展 延展 私有的内容
- @interface TRMyClass ()
- {
- int age;//私有的实例变量
- }
- @property(nonatomic,assign)char sex;//私有属性
- -(void)addMethod;//私有的方法
- @end
本案例中,分类TRConnectionServer声明,即NSString+TRConnectionServer.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- @interface NSString (TRConnectionServer)
- -(void)connection;
- @end
分类TRConnectionServer实现,即NSString+TRConnectionServer.m文件,完整代码如下所示:
- #import "NSString+TRConnectionServer.h"
- @implementation NSString (TRConnectionServer)
- -(void)connection{
- NSLog(@"连接服务器中...");
- }
- @end
主程序,即main.m,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "TRMyClass.h"
- #import "TRMyClass+AddMethod.h"
- #import "NSString+TRConnectionServer.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- TRMyClass* myClass = [[TRMyClass alloc]init];
- [myClass method1];
- [myClass method2];
- //[myClass addMethod];//私有方法,不能调用
- //可以给第三方或系统类添加能力
- NSString* str = [[NSString alloc]init];
- [str connection];
- }
- return 0;
- }
Objective-c---分类 、 扩展 、 ARC的更多相关文章
- Objective C中的ARC的修饰符的使用---- 学习笔记九
#import <Foundation/Foundation.h> @interface Test : NSObject /** * 默认的就是__strong,这里只是做示范,实际使用时 ...
- Linux 文件的详解[分类/扩展名/inode/block]
关于Linux文件的介绍 Linux里文件扩展名和文件类型没有关系,Linux系统中一切皆文件 关于Linux文件分类 纯文本文件(可以cat的) 二进制文件(Linux的可执行文件等,如/b ...
- UIButton利用分类扩展方法(封装)
UIButton+BackgroundColor.h #import <UIKit/UIKit.h> @interface UIButton (BackgroundColor) - (vo ...
- iOS-UIButton分类扩展(封装)
UIButton+BackgroundColor.h #import <UIKit/UIKit.h> @interface UIButton (BackgroundColor) - (vo ...
- OC分类(类目/类别) 和 类扩展 - 全解析
OC分类(类目/类别) 和 类扩展 - 全解析 具体见: oschina -> MyDemo -> 011.FoundationLog-OC分类剖析 http://blog.csdn. ...
- 【系统设计】不同分类的商品动态添加扩展属性的方法(WMS、小型电商)
在做公司WMS系统的时候,遇到了一个商品模块的设计问题,具体业务流程如下. 客户提供需要存放的商品清单,根据商品清单生成收货单给客户,然后生成入库单进行商品入库操作. 在生成这两个单之前首先要录入商品 ...
- iOS 数据持久化(扩展知识:模糊背景效果和密码保护功能)
本篇随笔除了介绍 iOS 数据持久化知识之外,还贯穿了以下内容: (1)自定义 TableView,结合 block 从 ViewController 中分离出 View,轻 ViewControll ...
- iOS之分类(category)
1.分类(category)的作用 1.1作用:可以在不修改原来类的基础上,为一个类扩展方法.1.2最主要的用法:给系统自带的类扩展方法. 2.分类中能写点啥? 2.1分类中只能添加“方法”,不能增加 ...
- 从损失函数优化角度:讨论“线性回归(linear regression)”与”线性分类(linear classification)“的联系与区别
1. 主要观点 线性模型是线性回归和线性分类的基础 线性回归和线性分类模型的差异主要在于损失函数形式上,我们可以将其看做是线性模型在多维空间中“不同方向”和“不同位置”的两种表现形式 损失函数是一种优 ...
- iOS开发系列--并行开发其实很容易
--多线程开发 概览 大家都知道,在开发过程中应该尽可能减少用户等待时间,让程序尽可能快的完成运算.可是无论是哪种语言开发的程序最终往往转换成汇编语言进而解释成机器码来执行.但是机器码是按顺序执行的, ...
随机推荐
- 关于for循环条件性能问题
昨天看一博客写到一条 尽量使用 for(int i=0,ct=list.Count();i<ct;i++){} 这样的格式,因为我平时一般都是用for(int i=0;i<list.Cou ...
- Collecting Bugs(POJ 2096)
Collecting Bugs Time Limit: 10000MS Memory Limit: 64000K Total Submissions: 3064 Accepted: 1505 ...
- windows下捕获dump
一般要捕获异常只需要两个函数:SetUnhandledExceptionFilter截获异常:MiniDumpWriteDump写dump文件.但是由于CRT函数可能会在内部调用SetUnh ...
- 在SQLite中创建数据库时总是提示错误?
答案:原先以为是因为编码影响的其实不是,是因为逗号和分号的原因,不是标准的英文状态下的格式
- python 爬虫
import urllib2 as url import re urls = 'http://www.php100.com/html/it/' headers = {'User-Agent':'Moz ...
- Swift - 自动布局库SnapKit的使用详解4(样例1:实现一个登录页面)
前面的几篇文章讲解了自动布局库SnapKit的使用方法.本文通过一个完整的样例(登录页面)来演示在实际项目中如何使用SnapKit来实现自动化布局的.1,效果图如下
- 如何在 Ubuntu 15.04 系统中安装 Logwatch
大家好,今天我们会讲述在 Ubuntu 15.04 操作系统上如何安装 Logwatch 软件,它也可以在各种 Linux 系统和类 Unix 系统上安装.Logwatch 是一款可定制的日志分析和日 ...
- 导航栏视图设置 tabbleView 是设置总背景图
//导航栏视图设置 tabbleView 是设置总背景图 //默认的时白色半透明(有点灰的感觉), UIBarStyleBlack,UIBarStyleBlackTranslucent ,UIBarS ...
- Ibatis.Net 入门示例(一)
新项目用的是Ibatis.Net.哥的感觉是NHibernate才是哥的最爱.没办法,即使重复,也要抽时间学习.努力做好这份工作再说吧. 一.Ibatis.Net-SQLServer2008 还是以哥 ...
- Phonebook 导入SD上的.vcf联系人
2014-01-11 17:29:22 1. 当用户选择Phonebook中从SD卡导入联系人的操作后,程序回调转到ImportVCardActivity,然后用户选择好要导入的.vcf文件,并点击“ ...