zoukankan      html  css  js  c++  java
  • 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。

    代码如下所示:

     
    1. #import <Foundation/Foundation.h>
    2. @interface TRMyClass : NSObject
    3. @property(nonatomic,assign)int property;
    4. -(void)method1;
    5. @end

    上述代码中,以下代码:

    1. @property(nonatomic,assign)int property;

    定义了一个属性,用于存储一个整型变量。它有两个参数,一个是nonatomic,它代表对属性赋值的时候不加锁,即在多线程环境下访问时可能会出现数据错误,如果需要在多线程环境下运行,为保证数据不会出现错误,可使用atomic参数,它会在对属性赋值的时候加锁。另一个参数是assign,对于C语言的基本数据类型,只能选取这个参数。

    上述代码中,以下代码:

    1. -(void)method1;

    定义了一个方法,该方法只是为了说明分类概念而定义的,所以没有任何实际意义,只是在函数体中输出一行提示。

    然后,在类TRMyClass的实现部分,将类中声明的方法进行实现。类TRMyClass的实现部分存放于Day05工程新添加的TRMyClass.m文件中。

    代码如下所示:

    1. #import "TRMyClass.h"
    2. @implementation TRMyClass
    3. -(void)method1{
    4. NSLog(@"method1执行了");
    5. }
    6. @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方法的声明。

    代码如下所示:

    1. #import "TRMyClass.h"
    2. @interface TRMyClass (AddMethod)
    3. {
    4. //int age;分类中不可以创建实例变量
    5. }
    6. -(void)method2;
    7. @end

    注意:在分类中不能创建新的实例变量,只能添加新的方法。

    然后,在分类AddMethod的实现部分,即在TRMyClass+AddMethod.m文件中,添加method2方法的实现。

    代码如下所示:

    1. #import "TRMyClass+AddMethod.h"
    2. @implementation TRMyClass (AddMethod)
    3. -(void)method2{
    4. self.property = 18;
    5. NSLog(@"添加了method2方法");
    6. }
    7. @end

    上述代码中,以下代码:

    1. -(void)method2{
    2. self.property = 18;
    3. NSLog(@"添加了method2方法");
    4. }

    在方法method2中可以访问分类AddMethod所属的主类TRMyClass中的属性property,将其赋值为18。

    步骤四:在主程序中使用分类

    首先在Day05工程的main.m文件中添加代码。

    代码如下所示:

    1. #import <Foundation/Foundation.h>
    2. #import "TRMyClass.h"
    3. #import "TRMyClass+AddMethod.h"
    4. int main(int argc, const char * argv[])
    5. {
    6. @autoreleasepool {
    7. // insert code here...
    8. TRMyClass* myClass = [[TRMyClass alloc]init];
    9. [myClass method1];
    10. [myClass method2];
    11. }
    12. return 0;
    13. }

    上述代码中,以下代码:

    1. TRMyClass* myClass = [[TRMyClass alloc]init];

    定义TRMyClass类的对象myClass。

    上述代码中,以下代码:

    1. [myClass method1];

    向对象myClass发送消息method1。方法method1声明和实现在TRMyClass类中,这和以前我们所学习的类方法的使用方法相同。

    上述代码中,以下代码:

    1. [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方法的声明。

    代码如下所示:

    1. #import "TRMyClass.h"
    2. //扩展 延展 私有的内容
    3. @interface TRMyClass ()
    4. {
    5. int age;//私有的实例变量
    6. }
    7. @property(nonatomic,assign)char sex;//私有属性
    8. -(void)addMethod;//私有的方法
    9. @end

    注意:在扩展中定义的实例变量、属性和方法都是私有的,只能被扩展所属的主类中的方法使用。

    扩展除了按照上述方法被放在单独的.h文件中,还可以将其放在扩展所属的主文件的.m文件中。

    代码如下所示:

    1. #import "TRMyClass.h"
    2. //扩展即可以放在.h文件中,也可以放在.m文件中
    3. //#import "TRMyClass_ADDExtention.h"
    4. //扩展 延展 私有的内容
    5. @interface TRMyClass ()
    6. {
    7. int age;//私有的实例变量
    8. }
    9. @property(nonatomic,assign)char sex;//私有属性
    10. -(void)addMethod;//私有的方法
    11. @end
    12. @implementation TRMyClass
    13. -(void)method1{
    14. NSLog(@"method1执行了");
    15. }
    16. -(void)addMethod{
    17. age = 100;
    18. self.sex = 'm';
    19. NSLog(@"method执行了");
    20. }
    21. @end

    上述代码中,以下代码:

    1. -(void)addMethod{
    2. age = 100;
    3. self.sex = 'm';
    4. NSLog(@"method执行了");
    5. }

    是在扩展所属的主文件的.m文件中实现方法的函数体。该方法在类外是不能被调用的,代码如下所示:

    1. #import <Foundation/Foundation.h>
    2. #import "TRMyClass.h"
    3. #import "TRMyClass+AddMethod.h"
    4. int main(int argc, const char * argv[])
    5. {
    6. @autoreleasepool {
    7. // insert code here...
    8. TRMyClass* myClass = [[TRMyClass alloc]init];
    9. [myClass method1];
    10. [myClass method2];
    11. //[myClass addMethod];//私有方法,不能调用
    12. }
    13. return 0;
    14. }

    上述代码中,以下代码:

    1. //[myClass addMethod];//私有方法,不能调用

    是在扩展所属的主类类外试图调用扩展中的方法addMethod,这样做编译是无法通过的。

    步骤七:为NSString类定义一个分类TRConnectionServer

    分类除了可以为自定义类添加外,还可以为没有源代码的第三方类或系统提供的类添加。例如,用步骤二中介绍的方法添加一个分类TRConnectionServer。

    代码如下所示:

    1. #import <Foundation/Foundation.h>
    2. @interface NSString (TRConnectionServer)
    3. -(void)connection;
    4. @end

    上述代码中,以下代码:

    1. @interface NSString (TRConnectionServer)

    是为Objective-C提供的Foundation类库中的NSString类创建一个分类TRConnectionServer。

    上述代码中,以下代码:

    1. -(void)connection;

    是在分类TRConnectionServer中添加一个方法connection。

    然后,在分类TRConnectionServer的实现部分,即在NSString+TRConnectionServer.m文件中,添加connection方法的实现。

    代码如下所示:

    1. #import "NSString+TRConnectionServer.h"
    2. @implementation NSString (TRConnectionServer)
    3. -(void)connection{
    4. NSLog(@"连接服务器中...");
    5. }
    6. @end

    步骤八:在主程序中使用分类TRConnectionServer

    首先在Day05工程的main.m文件中添加代码。

    代码如下所示:

    1. #import <Foundation/Foundation.h>
    2. #import "TRMyClass.h"
    3. #import "TRMyClass+AddMethod.h"
    4. #import "NSString+TRConnectionServer.h"
    5. int main(int argc, const char * argv[])
    6. {
    7. @autoreleasepool {
    8. // insert code here...
    9. TRMyClass* myClass = [[TRMyClass alloc]init];
    10. [myClass method1];
    11. [myClass method2];
    12. //[myClass addMethod];//私有方法,不能调用
    13. //可以给第三方或系统类添加能力
    14. NSString* str = [[NSString alloc]init];
    15. [str connection];
    16. }
    17. return 0;
    18. }

    上述代码中,以下代码:

    1. //可以给第三方或系统类添加能力
    2. NSString* str = [[NSString alloc]init];
    3. [str connection];

    可以直接创建一个NSString类的对象str,然后用该对象调用分类中定义的方法。

    1.4 完整代码

    本案例中,类TRMyClass声明,即TRMyClass.h文件,完整代码如下所示:

    1. #import <Foundation/Foundation.h>
    2. @interface TRMyClass : NSObject
    3. @property(nonatomic,assign)int property;
    4. -(void)method1;
    5. @end

    类TRMyClass实现,即TRMyClass.m文件,完整代码如下所示:

    1. #import "TRMyClass.h"
    2. //扩展即可以放在.h文件中,也可以放在.m文件中
    3. //#import "TRMyClass_ADDExtention.h"
    4. //扩展 延展 私有的内容
    5. @interface TRMyClass ()
    6. {
    7. int age;//私有的实例变量
    8. }
    9. @property(nonatomic,assign)char sex;//私有属性
    10. -(void)addMethod;//私有的方法
    11. @end
    12. @implementation TRMyClass
    13. -(void)method1{
    14. NSLog(@"method1执行了");
    15. }
    16. -(void)addMethod{
    17. age = 100;
    18. self.sex = 'm';
    19. NSLog(@"method执行了");
    20. }
    21. @end

    本案例中,分类AddMethod声明,即TRMyClass+AddMethod.h文件,完整代码如下所示:

    1. #import "TRMyClass.h"
    2. @interface TRMyClass (AddMethod)
    3. {
    4. //int age;分类中不可以创建实例变量
    5. }
    6. -(void)method2;
    7. @end

    分类AddMethod实现,即TRMyClass+AddMethod.m文件,完整代码如下所示:

    1. #import "TRMyClass+AddMethod.h"
    2. @implementation TRMyClass (AddMethod)
    3. -(void)method2{
    4. self.property = 18;
    5. NSLog(@"添加了method2方法");
    6. }
    7. @end

    本案例中,扩展AddExtention声明,即TRMyClass_AddExtention.h文件,完整代码如下所示:

    1. #import "TRMyClass.h"
    2. //扩展 延展 私有的内容
    3. @interface TRMyClass ()
    4. {
    5. int age;//私有的实例变量
    6. }
    7. @property(nonatomic,assign)char sex;//私有属性
    8. -(void)addMethod;//私有的方法
    9. @end

    本案例中,分类TRConnectionServer声明,即NSString+TRConnectionServer.h文件,完整代码如下所示:

    1. #import <Foundation/Foundation.h>
    2. @interface NSString (TRConnectionServer)
    3. -(void)connection;
    4. @end

    分类TRConnectionServer实现,即NSString+TRConnectionServer.m文件,完整代码如下所示:

    1. #import "NSString+TRConnectionServer.h"
    2. @implementation NSString (TRConnectionServer)
    3. -(void)connection{
    4. NSLog(@"连接服务器中...");
    5. }
    6. @end

    主程序,即main.m,完整代码如下所示:

     
    1. #import <Foundation/Foundation.h>
    2. #import "TRMyClass.h"
    3. #import "TRMyClass+AddMethod.h"
    4. #import "NSString+TRConnectionServer.h"
    5. int main(int argc, const char * argv[])
    6. {
    7. @autoreleasepool {
    8. // insert code here...
    9. TRMyClass* myClass = [[TRMyClass alloc]init];
    10. [myClass method1];
    11. [myClass method2];
    12. //[myClass addMethod];//私有方法,不能调用
    13. //可以给第三方或系统类添加能力
    14. NSString* str = [[NSString alloc]init];
    15. [str connection];
    16. }
    17. return 0;
    18. }
  • 相关阅读:
    好元素(good)
    三条线 (Standard IO)
    计数排序-自然顺序Comparable
    贪心算法之田忌赛马
    bzoj3400
    bzoj1704
    CF Round #456 (Div. 2)
    LA3029
    bzoj3000
    bzoj3623
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5049275.html
Copyright © 2011-2022 走看看