美文网首页
类相关延伸

类相关延伸

作者: 小李不木 | 来源:发表于2019-06-10 12:53 被阅读0次

    1:分类

    给某一个类扩充一些方法,并且不修改原来的代码。

    格式

    @interface  类名(分类名)

      @end 

     @implementation  类名

     @end

      使用注意:

                    1: 分类只能增加方法,不能增加成员变量。

                     2:分类方法实现中可以访问原来类中声明的成员变量。

    3:分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来类中的方法没法使用。

           如果原先类中实现了某个方法,分类中又实现了这个方法,当调用方法时。会优先调用分类中的方法。没有的话再去原类,再者是父类。如果一个类有多个分类,并且每个分类中都有这个方法的实现,则最后编译的那个分类会覆盖掉原来所有的方法。调用时,则调用最后编译的那个。

     分类的好处:

       一个庞大的类可以分模块开发。可以由多人来写。有利于团队开发 。

    分类可以访问原类的成员变量,但不能添加新的成员变量,只能添加方法,如果想添加变量,可以考虑通过继承创建子类。

       例如:

               给系统自带的NSString 字符串扩充一个方法。使它可以计算对象自身中所含的阿拉伯数字个数。

    - (int)  number 

     {

    for (int i = 0; i< self.length ; i++)

    //  遍历整个字符串

       {

             unichar c = [self  characterAtIndex  : i ];

    // 取出字符串中的某个字符

       }

            if  (c >='0'&& c<='9')

    //  判断字符的范围

               {

               count ++;

    //  计算加1 

                   }

              return  count ;

    }

     2: 类的本质

    类本身也是一个对象,是Class 类型的数据,简称类对象。

    当利用一个类创建对象时,先利用class 这个类创建出一个类对象,再用创建出来的类对象创建新的类对象。

    例如:

                 Person * p = [[person    alloc  ] init  ];

    Person * p2 = [[person    alloc  ] init  ];

     Person * p3 = [[person    alloc  ] init  ];

    获取p,p2,p3 的内存地址

             class  c = [p   class ];

    class  c2 = [p   class ];

    NSLog(@"%@,%@,c,c2");

    输出结果是一样的,这说明p 与P2 在内存中指向同一个类。

    也可以用  : Class  c3 = [ person class ];

    出c3 的结果也是相同的。

     Class 定义为:

      typedef  struct   objc  class  * class ;

       类名就代表着一个类对象。每个类只有一个类对象。

      此时  c  与 person 等价,都代表着类。

    Person * p4 = [  [c   alloc  ] init  ];

     3: + load  和 + initialize 方法

    1:+load 

       1>: 在程序启动时会加载所有的类和分类,并调用所有类的+ load 方法。

        2>:先加载父类,在加载子类,也就是先调用父类的+ load 方法,在调用子类的+ load 方法。

        3>: 先加载原类,在加载分类。

    4>:不管程序如何运行有没有用到这个类,都会调用类的+ load 方法。

      2: + initialize 方法

     1>: 在第一次使用这个类时,就会调用这个类的 initialize 方法。

        2>:一个类只会调用一次 initialize 方法,先调用父类的在调用子类的;先初始化父类,在初始化子类。

        3>:如果类和分类都有 initialize 方法,则优先使用分类中的 initialize 方法。

    4: description 方法

    可分为- description 方法和 + description 方法

    1>: 使用NSLog 和%@ 输出某个对象时,会调用对象的- description 方法,并拿到返回值输出。

                默认的输出是< 类名: 内存地址>

      2>: 使用NSLog 和%@ 输出某个类对象时,会调用类对象的+ description 方法,并拿到返回值输出。

                默认的输出是< 类名>

     例如:

    @interface  Person  : NSObject 

                {

                  int  age ;

                  double  weight;

               }

             - void  test ;

                @end 

    @implementation   Person 

    - void  test 

    NSLog (@''  调用  test 函数");

    }

         @end 

     int  main ()

    {

     Person * p = [  [person    alloc  ] init  ]; 

     p.age = 10;

     p.weight = 50;

    NSLog(@"%@,p");

    //  本来是想输出整个p 对象,可是默认输出为< 类名: 内存地址>。

    //  所以此时我们要想输出自己想要的结果,必须要重写- description方法。

    注意:

    - (id) description

    {   

      NSLog(@"%@,self "); 

    }

     这个是死循环,自己调用自己。

    + description 方法 与上述相似,不过它是类方法,要由类名调用。

    例如:

       int main ()

     {

       Class  c =  [ person   class ];

       NSLog(@"%@, c"); 

       return  0;

       默认输出为 : 类名

    SEL

     Person * p = [  [person    alloc  ] init  ]; 

    [   p   test ] ; 

    //   调用对象方法,给它发送一条 test 消息,本质就是发送一个SEL类型的数据。

    分为三步:

    1:把test  包装成SEL 类型的数据。

       2: 根据 SEL 数据 在类中找到相应的内存地址。

       3: 根据方法地址调用相应的方法。

    调用方法的两种方法:

    1: 直接调用 

       [   p   test ]

       2:间接调用   

    [p    performSelector :@ selector (test)]

    3:如果有参数

     [p    performSelector :@ selector  (test2:)  WihObject : 实参 ]

    方法的存贮位置:

     每个类的方法列表都存贮在类对象中

     每个方法都有一个与之对应的SEL 数据。

    根据一个SEL数据就可以找到方法的地址,然后调用方法。

    SEL类型的定义:

    typedef   struct   objc  select  *  SEL;

    相关文章

      网友评论

          本文标题:类相关延伸

          本文链接:https://www.haomeiwen.com/subject/grfzxctx.html