程序员

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

2020-11-16  本文已影响0人  Mr姜饼
上课知识回顾:

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


源码分析:

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 一定成立


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

上一篇 下一篇

猜你喜欢

热点阅读