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。

  • 相关阅读:
    高级特性(4)- 数据库编程
    UVA Jin Ge Jin Qu hao 12563
    UVA 116 Unidirectional TSP
    HDU 2224 The shortest path
    poj 2677 Tour
    【算法学习】双调欧几里得旅行商问题(动态规划)
    南洋理工大学 ACM 在线评测系统 矩形嵌套
    UVA The Tower of Babylon
    uva A Spy in the Metro(洛谷 P2583 地铁间谍)
    洛谷 P1095 守望者的逃离
  • 原文地址:https://www.cnblogs.com/HypeCheng/p/4629680.html
Copyright © 2011-2022 走看看