zoukankan      html  css  js  c++  java
  • 实例方法和类方法的调用

    在许多地方可以见到self和[self class]的调用方式,那么他们有区别吗?

     

    1 首先self是什么,它是指向实例变量首地址的指针(同c++的this一样)可以访问对象的资源。

    2 [self class] 首先看下class 它返回的是类对象(也就是isa指针),所以通过[self class]可以访问当前类的静态函数

    这样就引出两个问题 :A、[self class]为什么返回的是类对象 B、为什么[self class]可以访问当前类的类方法

    A、为什么[self class] 可以访问到类指针呢,可以看下NSObject的结构:

    @interface NSObject <NSObject> {

        Class isa  OBJC_ISA_AVAILABILITY;

    }

    //任何类都是继承于NSObject所以在内存中isa是首地址 ,self指向的就是isa的的地址。

    看下在runtime里面class是怎么调用的,首先是获取NSObject 类的isa变量,通过isa来返回类对象,所以也就是说class是返回了当前类。

    - (Class)class {

        return object_getClass(self);

    }

    Class object_getClass(id obj)

    {

        if (obj) return obj->getIsa();

        else return Nil;

    }

    B、为什么[self class]可以访问当前类的类方法

    首先先来学习下实例对象是怎么调用实例方法的,介绍运行时的知识中提到:对象对方法的调用是通过isa间接去调用,

    也就是说 [self Test1] 首先访问当前对象的isa,通过这个类对象在访问函数列表,从而调用方法Test1,概况起来就是:消息发送给对象,对象转交给其isa指向类去处理(类方法的调用也一样)

     

    @interface Sark : NSObject

    +(void)Test;

    @end

    类方法的调用顺序是 :[self class]返回类对象(isa指针)指向这个类如:Sark类,这个类里面又包含一个指向元类的类对象,当调用 [[self class] Test]跟对象调用一样,会通过当前类 访问其元类继而

    访问类方法。

     

    总结:无论是对象,还是类,都是通过访问其isa来调用函数 ,区别是调用的是实例方法还是类方法。

     

    我们先来看一个例子:

    +(void)Test{

        NSLog(@"static test");

    }

    -(void)Test1{

        NSLog(@"tst1");

    }

     

     

    - (void)viewDidLoad {

     

        [super viewDidLoad];

     

        Class c1 = object_getClass(self);

     

        Class c2 = [self class];

     

        Class c3 = object_getClass(c1);

     

        

     

        NSLog(@"c1:%p, c2:%p", c1, c2);

     

        

     

        [c1 Test];

     

        [c2 Test];

     

        [c3 Test1];

     

     

     

        IMP imp1 = class_getMethodImplementation(c1, @selector(Test1));

     

        imp1();

     

        

     

        IMP imp2 = class_getMethodImplementation(c2, @selector(Test1));

     

        imp2();

     

        //[[self class]Test];

     

        

     

        IMP imp3 = class_getMethodImplementation(c3, @selector(Test));

     

        imp3();

    }

     

     

     

        Class c1 = object_getClass(self);      Class c2 = [self class]; 都是返回当前类(等价关系)

     [c1 Test];和[c2 Test]; 在通过类的isa指针访问类方法

     

     

     

    3 那么[self class]除了可以访问静态函数,变量还有其他用处吗?看下面这个例子

     

    @interface Engine:NSObject<NSCopying>

    @end

     

    @implementation Engine

     -(id)copyWithZone:(NSZone *)zone{

       return [[[self class]allocWithZone:zone]init];

    }

    我们需要将消息发送给一个类,而不是一个实例变量。那么应该发送给哪个类呢?直觉告诉我们应该是Engine,像这样:[Engine allocWithZone:zone];

    但是这行代码只适用于Engine类,不适合它的之类。如果给它的子类Slant6发送copy消息,最后使用的是Engine类的拷贝而不是slant6类的拷贝,创建出来的时Engine对象。

    所以要使用[self class]他可以将消息发送给正在接受copy消息的对象所属的类。如果self是一个Slvant6的对象,就会发送给Slvant6。

  • 相关阅读:
    redis info详解
    redis数据类型-有序集合
    redis数据类型-集合类型
    redis数据类型-列表类型
    python——井字小游戏
    python——元组和字典学习笔记
    docker学习笔记
    中型公司网络架构拓扑与详解
    python——将图片转换为字符编码(linux版的)
    python——冒泡排序练习
  • 原文地址:https://www.cnblogs.com/HypeCheng/p/4629680.html
Copyright © 2011-2022 走看看