大家好,我是OB!

今天结合源码来看看NSObject常用方法

首先声明两个类,AnimalDog,继承关系如下

@interface Animal: NSObject
@interface Dog: Animal

1、 [Dog class][dog class]一样吗?

新手还在看,老手已经开始NSLog了。
结果是一样的。看看源码就清楚了,

+ (Class)class {return self;
}- (Class)class {return object_getClass(self);
}

这里要清楚三个概念,实例对象,类对象,元类对象。

我们创建的实例对象所拥有的实例方法,类方法,分别存储在类对象,元类对象。而 object_getClass就是获取self的类对象。

通过一个案例证实以上不是瞎说

struct ob_objc_class {Class isa;
};
int main(int argc, const char * argv[]) {@autoreleasepool {Dog *dog = [[Dog alloc] init];Class personClass = [dog class];struct ob_objc_class * personClass1 = (__bridge struct ob_objc_class *)(personClass);Class personMetaClass = object_getClass(personClass);}return 0;
}

打上断点,输入指令可以看到,dogisa指向了类对象dogClass,而 类对象dogClassisa指向了元类对象dogMetaClass

2、super

Dog 的init中,下面打印什么?

- (instancetype)init{self = [super init];if (self) {NSLog(@"%@",[self class]);NSLog(@"%@",[super class]);NSLog(@"%@",[self superclass]);NSLog(@"%@",[super superclass]);}return self;
}

打印结果

 Test_01[28917:2075877] DogTest_01[28917:2075877] DogTest_01[28917:2075877] AnimalTest_01[28917:2075877] Animal

这里是对runtimeobjc_msgSend() objc_msgSendSuper()super关键字的理解

首先[self class][super class]编译过后会变成

objc_msgSend(self, sel_registerName("class"));
struct __rw_objc_super {self,class_getSuperclass(objc_getClass("Dog")),
};objc_msgSendSuper(__my__rw_objc_super,sel_registerName("class"));

最重要的是这两个方法的接受者,也就是方法调用者都是self

super关键字,表示方法查找从父类开始,直接跳过了self,但是接受者还是self,所以当他们在NSObject找到class实现时,

//NSObject中class实现
- (Class)class {return object_getClass(self);
}

返回的都是Dog,

同理,superClass方法也是一样,只是方法查找的起始位置不一样,实现都是一样,

+ (Class)superclass {return self->superclass;
}
- (Class)superclass {return [self class]->superclass;
}

所以返回的都是Animal

3、isMemberOfClass

类A的类型 ?类B的类型,比较同一种类,不包含子父类
观察下面代码

NSLog(@"%d",[self isMemberOfClass:[Dog class]]); //1
NSLog(@"%d",[Dog isMemberOfClass:[Dog class]]);  //0

为什么会出现这样的结果?先看看它的实现,可以看出这是只有当两个对象的类对象相等时,才能返回YES

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

注意类方法和实例方法中的self是不同的,类方法中的self是类对象Dog,而实例方法中的selfdog

[Dog isMemberOfClass:[Dog class]]中,相当于是object_getClass(Dog) == [Dog class];object_getClass(Dog)其实是类对象的isa指向的元类对象dogMetaClass,所有不相等,

改成如下代码就可以了

[Dog isMemberOfClass:object_getClass([Dog class])] //1

4、isKindOfClass

类A是否是类B,或者是B的子类

NSLog(@"%d",[self isKindOfClass:[Dog class]]); //1
NSLog(@"%d",[Dog isKindOfClass:[Dog class]]); //0
NSLog(@"%d",[Dog isKindOfClass:object_getClass([Dog class])]); //1

isMemberOfClass 一样,只不过是多了个for循环,因为会去父类查找。

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

5、isEqual

比较两个对象是否完全相等,比较内存地址

NSLog(@"%d",[self isEqual:[Dog class]]); // 0
NSLog(@"%d",[Dog isEqual:[Dog class]]);  // 1

先看源码,就是完全比较两边是不是完全相等,

+ (BOOL)isEqual:(id)obj {return obj == (id)self;
}- (BOOL)isEqual:(id)obj {return obj == self;
}

所以[dog1 isEqual:dog2] 不相等,因为 dog1 != dog2

Dog *dog1 = [[Dog alloc] init];
Dog *dog2 = [[Dog alloc] init];
NSLog(@"%d", [dog1 isEqual:dog2]); //0
NSLog(@"%d", [[dog1 class] isEqual:[dog2 class]]); // 1

注意:如果是常量就不太一样了哦

NSString *s1 = @"werthjgfcdxsdfghgfdsdfg";
NSString *s2 = @"werthjgfcdxsdfghgfdsdfg";
NSLog(@"%d", [s1 isEqual:s2]); // 1

这里是相等的哦,因为s1和s2是常量,她们的内存地址一样哦。

今天先到这里!大家好我是OB!

对了,获取编译后的代码在终端指令

xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc 需要编译的文件 -o 编译后的文件名
例如
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc /Users/OB/Desktop/Test_01/Test_01/main.m -o myMain.cpp

NSObject常用方法superclass,[super superclass],isMemberOfClass,isKindOfClass,isEqual,clang相关推荐

  1. NSObject常用方法 和反射

    一. NSObject 常用方法 1. 判断一个对象是否属于某个类或子类 [对象 isKindOfClass:[类名]];  返回 BOOL 值 2. isMemberOfClass判断对象是否属于某 ...

  2. NSObject的isa和superclass区别

    这篇博客介绍的就是网上很流行的一张图关于isa和superclass的关系的解释! 温馨提示:如果你没有接触类的对象不了解的话,这篇博客有点费解,建议先看一下深入探究NSObject对象. 一.isa ...

  3. iOS runtime 底层详解、内部原理、场景应用

    前言学:位域和共用体 一:isa指针--runtime之前的学习 1.1:苹果应用的按位或.按位与 二:类对象信息 2.1:类对象信息:rw_t 2.2:类对象信息:方法缓存(很关键) 2.2:类对象 ...

  4. 浅析class 、superclass、isMemberOfClass、isKindOfClass

    经典图 抛出问题 BOOL res1 = [(id)[NSObject class] isKindOfClass:[NSObject class]];BOOL res2 = [(id)[NSObjec ...

  5. 从源码理解runtime之super、superclass知识点

    跟大家分享一道关于super和superclass的面试题,也是比较常见的面试题,请看下面的代码: 请问当前的4个结果输出是多少?我们平时写代码估计也不会这么写,面试官问你这些问题,主要是看你对sup ...

  6. self、 superclass 、 super的区别

    self. superclass . super self : 当前方法的调用者 class:获取方法调用者的类对象 superclass:获取方法调用者的父类对象 super:不是一个指针,编译指示 ...

  7. super,class,superClass区别

    -(void)test{//获取当前方法调用者的类NSLog(@"%@",[self class]); //当前方法调用者的父类 NSLog(@"%@",[se ...

  8. 【OC底层】OC对象本质,如 isa, super-class

    Objective-C的本质 1.我们编写的Objective-C,底层现实都是C/C++,代码生成步骤如下: 2.在OC中的所有面向对象的实现,都是基于C/C++的数据结构实现的 3.将Object ...

  9. Exception in thread “main“ java.lang.ClassCastException: test.SuperClass cannot be cast to test.SubC

    我创建的类是如下情况,编译过程中没有报错,但是当我执行该代码的时候,终端出现以下异常 Exception in thread "main" java.lang.ClassCastE ...

最新文章

  1. Linux终端设备详解
  2. freetype 安装
  3. C语言库函数(Q类字母)
  4. 超过12000个零件,钢琴就是一部复杂的机器
  5. w8服务器dns修改,Win8.1系统的DNS地址如何修改?修改win8.1系统DNS地址图文教程
  6. 深入探究VC —— 资源编译器rc.exe(3)
  7. lamp源码三层结构
  8. excel中的颜色代码(colorIndex)
  9. 小程序源码:全新独立后台月老办事处一元交友盲盒-多玩法安装简单
  10. 360校企培训:安全导论-试卷
  11. 高速公路测量计算CASIO程序全套
  12. win7电脑蓝屏没有修复计算机,Win7旗舰版系统电脑老是出现蓝屏的修复教程
  13. Django之DRF自定义action
  14. Mysql update from 使用
  15. C++ 学习(基础语法篇)
  16. 手机软件测试英语,手机软件测试,mobile phone software testing,音标,读音,翻译,英文例句,英语词典...
  17. LifeSmart云起局域网直接控制向往背景音乐
  18. CPU架构与指令集的关系
  19. 最新使用Mac自带的启动转换助理(Boot Camp)安装Windows10的详细方法教程-macbookpro 10.13.4
  20. 心目中的编程高手,经典计算机书籍作者介绍(部分,以后不定期更新)!

热门文章

  1. 手写django框架
  2. quotacheck命令不能创建aquota.user和aquota.group文件解决方法 原
  3. ChatGPT - 使用chatgpt + mindshow 快速生成PPT
  4. 每日一题-9/6-消失的数字
  5. 别人的 阿里校招 面试总结
  6. 【转】:北京7月1日起公积金缴存比例调整为12%
  7. ERwin2020导出HTML,New Features in Erwin Release 2020 R1
  8. PostgreSQL事物隔离级别之可重复读
  9. aptitude 与 apt-get
  10. Android源码级别开发