• Objective-C 【类对象及SEL存储方式】


    ———————————————————————————————————————————
    类的本质——类对象

    一段代码:

    #import <Foundation/Foundation.h>

    @interface Person : NSObject
    -(void)run;
    +(void)run;
    @end

    @implementation Person
    -(void)run
    {
        NSLog(@"对象方法run!");
    }

    +(void)run
    {
        NSLog(@"类方法run!");
    }
    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
            Person *p1=[Person new];
            [p1 run];
            
            [Person run];
            
            Person *p2=[Person new];
            
    //        其实类也是一个对象,他也有他的类。比如Person其实就是一个对象,我们将这种对象称之为 类对象。而p1我们称之为类类型的实例对象,这两个是不一样,注意叫法区分。
    //        类对象属于Class类型
            
    //        类对象的获取方式:
    //        ①通过实例对象获取:
            Class c1=[p1 class];//这两句话都是得到Dog这个类对象,需要注意的是,Class类声明类对象的时候,直接就是Class 变量名,变量名(如c1)前面是没有符号的(这是结构体,不是指针)
            Class c2=[p2 class];
    //        我们打印检测一下c1、c2的地址如何
            NSLog(@"c1=%p",c1);//c1=0x100001200
            NSLog(@"c2=%p",c2);//c2=0x100001200
    //        显然c1、c2虽为累类型不同的实例对象调用,但他们属于同一个累类型,所以说他们都是返回的Dog这个类对象的地址
            
    //        当然我们还可以用%@的格式查看一下这个类类型的信息,显然输出的结果是  Person
            NSLog(@"%@",c1);//Person
            NSLog(@"%@",c2);//Person
            
    //        ②通过类名获取
            Class c3=[Person class];
            NSLog(@"c3=%p",c3);
            
            NSLog(@"%@",c3);
        }
        return 0;
    }


    ———————————————————————————————————————————
    类对象的使用


    一段代码:

    #import <Foundation/Foundation.h>

    @interface Person : NSObject
    -(void)test;
    +(void)test;
    @end

    @implementation Person
    -(void)test
    {
        NSLog(@"-test!");
    }

    +(void)test
    {
        NSLog(@"+test!");
    }
    @end

    int main(int argc, const char * argv[]) {
        @autoreleasepool {
    //        获取类对象
            Class c1=[Person class];//此时c1就等同于Person
            
    //        类对象的使用:
    //        ①使用类对象创建实例对象
            Person *p1=[c1 new];//这句话等同于 Person *p1=[Person new];
    //        c1 *p1=[c1 new];//★但是我们却不能用这种方法进行创建实例对象,这一点一定要记住!
            [p1 test];//用实例对象p1调用对象方法test,调用成功说名创建实例对象成功
    //        ②使用类对象调用类方法
            [c1 test];
        }
        return 0;
    }



    ———————————————————————————————————————————
    类对象的存储及SEL(理解)

    在实例对象调用方法的时候,首先在类对象中进行判断(判断当前调用的方法的SEL   和   类的代码区里的SEL相比是不是一致),然后确定是不是调用。

    下面介绍一下SEL:

    ★SEL全称selector表示方法的存储位置★

    例如:

    Person *p = [ [ Person alloc ] init ] ;
    [ p test ] ;   //这里test是一个对象方法

    寻找方法的过程:
    ①首先把test这个方法名包装成sel类型的数据
    ②根据sel数据找到对应的方法地址
    ③根据方法地址调用相应的方法
    (注意一下,这个查找sel数据的过程有缓存,第一次找一个一个找非常的费时且非常耗性能,但是第二次就直接使用了)

    关于_cmd: 每个方法的内部都有一个_cmd: ,他代表了当前方法。

    ★注意:SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找寻对应方法的地址,找到方法地址后就可以调用方法了。这些都是运行时的特性,发消息就是发送SEL,然后根据SEL找到地址,进而调用方法。


    一段代码并不完整(只是测试用的):

    //        如果用SEL来调用test方法的话,我们可以这样做:
    //        手动将test方法(对象方法)包装成 SEL 类型
            SEL s1=@selector(test);   //这里和Class声明类对象的时候是一样的,属于结构体类型
            [p1 performSelector:s1];
    //        上面两句话,和  [p1 test]; 的作用是一模一样的
            [Person performSelector:s1];  //performSelector:s1就等同于test
    //        当然这里也可以调用类方法
     

    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    GDI+学习之------色彩与图像
    2015小米暑期实习笔试题_懂二进制(位运算)
    拷贝构造函数和赋值函数
    HDU
    react-router中,<switch>
    Navicat for MySQL
    maven项目创建3 (依赖版本冲突)
    maven项目创建2
    maven项目创建
    Eclipse 开发环境修改及MAVEN配置
  • 原文地址:https://www.cnblogs.com/wzy294250051/p/4787893.html
Copyright © 2020-2023  润新知