美文网首页
OC对象调用方法原理

OC对象调用方法原理

作者: 天津的树懒 | 来源:发表于2020-02-20 17:17 被阅读0次

如果对OC对象的类型还不清楚的童鞋,请移步本人之前撰写的OC对象的分类,那里有详尽的讲解。

本文主要讲解OC对象调用方法的原理:

1、isa指针的调用:

  • 某个类的实例对象的isa指针指向这个类的类对象;
  • 类对象的isa指针指向这个类的元类对象;
  • 元类对象的isa指针指向基类(NSObject)的元类对象;
  • 基类的元类对象的isa指针指向它自己。

2、superclass指针的调用:

  • 某个类的类对象里面的superclass指针指向这个类的父类的类对象。因为OC中所有的类都是继承于基类(NSObject)的,所以最后都会指向基类的类对象,基类的类对象里面的superclass指针指向nil;
  • 某个类的元类对象里面的superclass指针指向这个类的父类的元类对象,最后都会指向基类的元类对象;
  • 基类的元类对象里面的superclass指针指向基类的类对象。

3、实例对象调用实例方法的原理:

当某个类的实例对象调用某个实例方法的时候,系统先根据实例对象里面的isa指针找到这个类的类对象,看看这个类对象里面有没有这个实例方法,如果有的话就进行调用,如果没有的话就再根据这个类对象里面的superclass指针找到这个类的父类的类对象,再看看这个类对象里面有没有这个实例方法,如果没有的话就再根据这个类对象里面的superclass指针再找它的父类的类对象,这样一直往上找,直到找到基类(NSObject)的类对象,因为基类的类对象里面的superclass指针指向的是nil,所以在里面如果还是找不到这个实例方法的话,系统就会报"nrecognized selector sent to instance..."(方法找不到)错误。

4、类对象调用类方法的原理:

当某个类调用某个类方法的时候,其内部的实现原理为:系统先根据这个类的class对象里面的isa指针找到这个类的meta-class对象,如果这个meta-class对象里面有这个类方法的话就进行调用,如果没有的话再根据这个meta-class对象里面的superclass指针找到这个类的父类的meta-class对象,再看看这个meta-class对象里面有没有这个类方法,如果没有的话就再根据这个meta-class对象里面的superclass指针再找到它的父类的meta-class对象,这样一直往上找,直到找到基类(NSObject)的meta-class对象,如果里面还是没有这个类方法的话就再根据基类的meta-class对象里面的superclass指针找到基类的class对象,再看看这个class对象里面有没有这个类方法,如果还是找不到的话,系统就会报"nrecognized selector sent to instance..."(方法找不到)的错误了。

OC对象调用关系
#import <Foundation/Foundation.h>
#include <objc/message.h>

//自定义类
@interface Person : NSObject <NSCopying>
{
    @public
    int _age;
}

@property (nonatomic, assign) int no;

- (void)personInstanceMethod;

+ (void)personClassMethod;

- (void)test;

@end

@implementation Person

- (void)personInstanceMethod
{
    NSLog(@"personInstanceMethod");
}

+ (void)personClassMethod
{
    NSLog(@"personClassMethod");
}

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

@end

//自定义类
@interface Student : Person <NSCoding>
{
    @public
    int _weight;
}

@property (nonatomic, assign) int height;

- (void)studentInstanceMethod;

+ (void)studentClassMethod;

- (void)test;

@end

@implementation Student

- (void)studentInstanceMethod
{
    NSLog(@"studentInstanceMethod");
}

+ (void)studentClassMethod
{
    NSLog(@"studentClassMethod");
}

- (void)test
{
    NSLog(@"Student test");
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
//------------------------- 父类的实例对象调用父类的实例方法 ------------------------
        Person *person = [[Person alloc] init];
        person->_age = 10;
        
        [person personInstanceMethod];
        
        /**
         ·上面调用person对象的personInstanceMethod方法,实质上在Runtime层面上讲是消息的发送,如下所示,相当于给person对象发送一条personInstanceMethod消息;
         ·下面代码的执行原理:根据Runtime,系统会根据Person类的实例对象里面的isa指针找到Person类的类对象,然后在这个类对象的实例方法列表中寻找personInstanceMethod实例方法,然后再进行调用。
         */
        objc_msgSend(person, @selector(personInstanceMethod));
        
 //--------------------------- 父类的类对象调用父类的类方法 ------------------------
        [Person personClassMethod];
        
        /**
         ·上面调用Person类的personClassMethod方法实质上可以写成如下的代码;
         ·下面代码的执行原理:根据Runtime,系统会根据Person类的类对象里面的isa指针找到它的元类对象,然后在这个元类对象的类方法列表中寻找personClassMethod类方法,然后再进行调用。
         */
        objc_msgSend([Person class], @selector(personClassMethod));
        
 //--------------------------- 子类的实例对象调用父类的实例方法 ------------------------
        /**
         ·Student类继承自Person类,Person类继承自NSObject,他们之间是父子关系;
         ·下面代码的执行原理:根据Runtime,系统会根据Student的实例对象里面的isa指针找到Student的类对象,根据类对象里面的superclass指针找到Student类的父类Person类的类对象,在这个类对象的实例方法列表中找到personInstanceMethod实例方法,然后再进行调用。
         */
        Student *student = [[Student alloc] init];
        [student personInstanceMethod];
     
//--------------------------- 子类的类对象调用父类的类方法 ------------------------
        /**
         下面代码的执行原理:根据Runtime,系统会根据Student类对象里面的isa指针找到Student类的元类对象,然后根据这个元类对象里面的superclass指针找到Student类的父类Person类的元类对象,然后在这个元类对象的类方法列表中寻找personClassMethod类方法,然后再进行调用。
         */
        [Student personClassMethod];
        
//--------------------------- 子类的类对象调用基类的类方法 ------------------------
        /**
         下面代码的执行原理:根据Runtime,系统会根据Student类对象里面的isa指针找到Student类的元类对象,然后根据这个元类对象里面的superclass指针找到Student类的父类Person类的元类对象,然后根据Person类的元类对象里面的superclass指针找到基类的元类对象,然后在这个元类对象里面的类方法列表中找到load类方法,然后再进行调用。
         */
        [Student load];
        
//--------------------------- 子类重写父类的方法会覆盖父类的方法 ------------------------
        /**
         下面代码的执行原理:根据Runtime,系统会根据student实例对象里面的isa指针找到student类的类对象,然后在这个类对象里面的实例方法列表中找到test实例方法,然后再进行调用,整个调用过程就结束了,就不会再继续往student类的父类的类对象中去找了。这也就是为什么子类重写父类的方法后,会把父类的方法覆盖掉的原因。
         */
        [student test];
    }
    
    return 0;
}

Github Demo

”三人行,必有我师焉“, 欢迎各位批评指正。
如果您还觉得我写的不错的话请您点赞加关注,您的肯定是我前进的最大动力!
我是爱学习也爱您的树懒O(∩_∩)O

相关文章

  • OC对象调用方法原理

    如果对OC对象的类型还不清楚的童鞋,请移步本人之前撰写的OC对象的分类,那里有详尽的讲解。 本文主要讲解OC对象调...

  • 关于Category--你需要知道的

    知识铺垫-OC对象以及方法调用Category的实现原理Category和Class Extension 类扩展的...

  • 七.Block初识

    block的原理是什么?本质是什么?本质是OC对象,block封装了函数调用以及函数调用环境的OC对象 __blo...

  • block详解

    18:block的原理是怎样的?本质是什么? 封装了函数调用以及调用环境的oc对象 block本质也是一个oc对象...

  • OC重学第二天

    一. 类方法 OC 中方法分为两种.对象方法/实例方法如果想要调用对象方法必须要创建对象,通过对象来调用类方法.类...

  • swift学习笔记-OC与swift区别,从OC到swift你可

    创建对象 OC:alloc initWith Swift:(XXX:) 调用方法 OC:[uicolor redc...

  • 1.5、iOS面试题之runtime

    1.方法交换的原理及应用场景 在OC语言的runtime特性中,调用一个对象的方法就是给这个对象发送消息。是通过查...

  • 这些个问题

    OC runtimemethod_swizzled使用和原理:方法的调用实际上是消息发送,一个对象收到消息之后会在...

  • iOS 底层学习12 -- Block三种类型

    oc对象可以调用class方法看下这个对象的类型!!!所以block也是可以的 所以实例对象调用superclas...

  • OC链式编程的一个实践

    所谓链式编程,基本都是调用一个方法的时候返回对象本身,然后可以继续调用方法。以OC为例: 不过OC使用中括号调用方...

网友评论

      本文标题:OC对象调用方法原理

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