美文网首页程序员
三:类内存结构--知识扩展

三:类内存结构--知识扩展

作者: Mr姜饼 | 来源:发表于2020-11-16 17:53 被阅读0次
上课知识回顾:

证明:对象方法存在类里面,类方法存在元类里面!!!!!


源码分析:

class_getInstanceMethod:获取类的对象方法!!

Method class_getInstanceMethod(Class cls, SEL sel)
{
    if (!cls  ||  !sel) return nil;

    // This deliberately avoids +initialize because it historically did so.

    // This implementation is a bit weird because it's the only place that 
    // wants a Method instead of an IMP.

#warning fixme build and search caches
        
    // Search method lists, try method resolver, etc.
    lookUpImpOrForward(nil, sel, cls, LOOKUP_RESOLVER);

#warning fixme build and search caches

    return _class_getMethod(cls, sel);
}
static Method _class_getMethod(Class cls, SEL sel)
{
    mutex_locker_t lock(runtimeLock);
    return getMethod_nolock(cls, sel);
}
getMethod_nolock(Class cls, SEL sel)
{
    method_t *m = nil;

    runtimeLock.assertLocked();

    // fixme nil cls?
    // fixme nil sel?

    ASSERT(cls->isRealized());

    while (cls  &&  ((m = getMethodNoSuper_nolock(cls, sel))) == nil) {
        cls = cls->superclass;
    }

    return m;
}
getMethodNoSuper_nolock(Class cls, SEL sel)
{
    runtimeLock.assertLocked();

    ASSERT(cls->isRealized());
    // fixme nil cls? 
    // fixme nil sel?

    auto const methods = cls->data()->methods();
    for (auto mlists = methods.beginLists(),
              end = methods.endLists();
         mlists != end;
         ++mlists)
    {
        // <rdar://problem/46904873> getMethodNoSuper_nolock is the hottest
        // caller of search_method_list, inlining it turns
        // getMethodNoSuper_nolock into a frame-less function and eliminates
        // any store from this codepath.
        method_t *m = search_method_list_inline(*mlists, sel);
        if (m) return m;
    }

    return nil;
}

核心代码:auto const methods = cls->data()->methods();

** 是不是验证了我们上节课对应的,取类的对象方法,即在data()->methods()中取,有的话返回地址,没有的话返回0

源码分析:

class_getClassMethod:获取类的类方法(等价于 获取该类 元类 的实例化方法)

Method class_getClassMethod(Class cls, SEL sel)
{
    if (!cls  ||  !sel) return nil;

    return class_getInstanceMethod(cls->getMeta(), sel);
}

    Class getMeta() {
        if (isMetaClass()) return (Class)this;
        else return this->ISA();
    }

总结: 获取一个类的类方法 其实等价于,获取该元类的实例化方法 (如果是元类的话,则不需要取该元类的元类了,直接返回,不继续递归了,不然的话会无限递归循环)


结合上小节的实例lldb来分析:


@interface LGPerson : NSObject
{
    NSString* interst;
    
}
@property (nonatomic, copy) NSString *nickName;
@property (nonatomic, strong) NSString *name;


//对象方法
- (void)test_InstanceMethod;
//类方法
+ (void)test_ClassMethod;
@end

论证:

1. Method method1 = class_getInstanceMethod([LGPerson Class], @selector(test_InstanceMethod));//有

1 :LGPerson类拥有"test_InstanceMethod"的对象方法,所以此处 可以 得到结果

 Class metaClass = objc_getMetaClass("LGPerson");//获取元类
 Method method2 = class_getInstanceMethod(metaClass, @selector(test_InstanceMethod));//无

2 :LGPerson类的 元类 没有"test_InstanceMethod"的对象方法,拥有类方法"test_ClassMethod"的方法,所以此处 不可以 得到结果

Method method3 = class_getInstanceMethod([LGPerson Class], @selector(test_ClassMethod));//无

3 :LGPerson类,没有类方法"test_ClassMethod"的方法,所以此处 不可以 得到结果

 Class metaClass = objc_getMetaClass("LGPerson");//获取元类
 Method method4 = class_getInstanceMethod(metaClass, @selector(test_ClassMethod));//有

4 :LGPerson类的 元类 ,拥有类方法"test_ClassMethod"的方法,所以此处 可以 得到结果

const char *className = class_getName([LGPerson Class]);
Class metaClass = objc_getMetaClass(className);
//得不到结果!
Method method1 = class_getClassMethod(pClass, @selector(test_InstanceMethod));//无
//得不到结果!
Method method2 = class_getClassMethod(metaClass, @selector(test_InstanceMethod));//无

//可以得到结果~
Method method3 = class_getClassMethod(pClass, @selector(test_ClassMethod));//有
//可以得到结果~(元类的话,则不需要取该元类的元类了,直接返回,不继续递归了,不然的话会无限递归循环)
Method method4 = class_getClassMethod(metaClass, @selector(test_ClassMethod));//有

源码分析:

[Class isKindOfClass]: 类方法

+ (BOOL)isKindOfClass:(Class)cls {

    for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

初始赋值为该类的 “元类”,循环从该元类的父类找,直到找到该元类及其父类与参数cls等同的情况,才返回 “true”,否则返回“false”


源码分析:

[Class isMemberOfClass]:类方法

+ (BOOL)isMemberOfClass:(Class)cls {
    return self->ISA() == cls;
}

初始赋值为该类的 “元类”,判断该元类是否与参数“cls”等同,相同返回 “true”,否则返回“false”


源码分析:

[objc isKindOfClass]:对象方法

- (BOOL)isKindOfClass:(Class)cls {
    for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
        if (tcls == cls) return YES;
    }
    return NO;
}

初始赋值为该“类“,循环从该类的父类找,直到找到该类及其父类与参数cls等同的情况,才返回 “true”,否则返回“false”


源码分析:

[objc isKindOfClass]:对象方法

- (BOOL)isMemberOfClass:(Class)cls {
    return [self class] == cls;
}

初始赋值为该“类“,判断该类是否与参数cls等同,等同返回 “true”,否则返回“false”

实战:
BOOL re1 = [(id)[NSObject class] isKindOfClass:[NSObject class]]; 

1:此处调用"类方法",NSObject的"元类"不同于NSObject,跑循环之后可以找到与NSObject相同的类 ,所以此处为 ”true“

BOOL re2 = [(id)[NSObject class] isMemberOfClass:[NSObject class]];

2:此处调用"类方法",NSObject的"元类"不等同于NSObject,所以此处为 ”false“

BOOL re3 = [(id)[LGPerson class] isKindOfClass:[LGPerson class]];

3:此处调用"类方法",LGPerson的"元类"不等同于LGPerson,即使循环查找父类,也不存在等同的情况,所以此处为 ”false“

BOOL re4 = [(id)[LGPerson class] isMemberOfClass:[LGPerson class]];

4:此处调用"类方法",LGPerson的"元类"不等同于LGPerson,所以此处为 ”false“

const char *className = class_getName(LGPerson.class);
Class metaClass = objc_getMetaClass(className);
BOOL re5 = [(id)[LGPerson class] isMemberOfClass:metaClass];     

5:此处调用"类方法",LGPerson的"元类"不等同于LGPerson的元类,所以此处为 ”ture"

BOOL re6 =  [(id)[LGPerson class] isKindOfClass:[NSObject class]];

6:此处调用"类方法",LGPerson的"元类"虽然不等同于NSObject类,但是跑父类的循环,会找到与NSObject相同的类,所以此处为 ”ture"

BOOL re7 = [(id)[NSObject alloc] isKindOfClass:[NSObject class]];       
BOOL re8 = [(id)[NSObject alloc] isMemberOfClass:[NSObject class]];    
BOOL re9 = [(id)[LGPerson alloc] isKindOfClass:[LGPerson class]];     
BOOL re10 = [(id)[LGPerson alloc] isMemberOfClass:[LGPerson class]];   

7:true 8:true 9: true 10:true 不多说什么

**记住:只要isMemberOfClass成立,则isKindOfClass 一定成立


完结撒花✿✿ヽ(°▽°)ノ✿

相关文章

  • 三:类内存结构--知识扩展

    上课知识回顾: 证明:对象方法存在类里面,类方法存在元类里面!!!!! 源码分析: class_getInstan...

  • Category分类

    一、分类 扩展(extension)类的一部分编译时期加载隐藏类的私有属性对象的内存布局确定(内存空间、结构体) ...

  • Swift 语言简单介绍(二)

    本片文字主要介绍: 结构体 类 协议 扩展 闭包 结构体 类 协议 扩展 枚举 闭包

  • Swift:面向对象(二)

    一、继承(针对类)二、多态(针对类)三、协议(枚举、结构体、类都可以)四、扩展(枚举、结构体、类都可以)五、访问控...

  • java开发两年,类加载器及其加载过程都搞不明白,那你工作可能不

    内存结构概述 内存结构简图: 内存结构详细图: 中文: 英文: Java基础知识大全[https://jq.qq....

  • JVM

    简介 Jvm 系列一:Java类的加载机制Jvm系列二:JVM内存结构 --内存泄漏与内存溢出Jvm系列三:GC算...

  • 《六》、类结构扩展

    一、成员属性封装    面向对象之中的最核心组成就是类与对象,但是在进行类开发的时候,也可以遵从面向对象的主要特征...

  • jvm学习

    1,java类的加载机制2,JVM内存结构3,GC算法 垃圾收集器4,jvm知识点总览

  • (SPI)3.dubbo spi代码分析

    看三个方法,静态扩展类,adapter扩展类,activate扩展类。先看getExtension 获取实现类对象...

  • Bridge(桥接)模式

    特点:了解Bridge模式需要先了解类扩展的两个维度:类的实现层次结构和类的功能层次结构。类的实现层次结构:可理解...

网友评论

    本文标题:三:类内存结构--知识扩展

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