当前位置:   article > 正文

iOS Runtime面试题(代码题 一)_ios father与son面试题

ios father与son面试题

题目一:下面的代码输出什么?

  1. @implementation Son : Father
  2. - (id)init {
  3. self = [super init];
  4. if (self) {
  5. NSLog(@"%@", NSStringFromClass([self class]));
  6. NSLog(@"%@", NSStringFromClass([super class]));
  7. }
  8. return self;
  9. }
  10. @end

结果: Son / Son

分析:

对于上面的答案,第一个的结果应该是我们的预期结果,但是第二个结果却让我们很费解了。

那我们利用前面文章讲过的知识点来分析一下整个的流程。

因为,Son 及 Father 都没有实现 -(Class)calss 方法,所以这里所有的调用最终都会找到基类 NSObject 中,并且在其中找到 -(Class)calss 方法。那我们需要了解的就是在 NSObject 中这个方法的实现了。

在 NSObject.mm 中可以找到 -(Class)class 的实现:

  1. - (Class)class {
  2. return object_getClass(self);
  3. }

在 objc_class.mm 中找到 object_getClass 的实现:

  1. Class object_getClass(id obj)
  2. {
  3. if (obj) return obj->getIsa();
  4. else return Nil;
  5. }

ps:上面的方法定义可以去官方OpenSource中下载源码哦。

可以看到,最终这个方法返回的是,调用这个方法的 objc 的 isa 指针。那我们只需要知道在题干中的代码里面最终是谁在调用 -(Class)class 方法就可以找到答案了。

接下来,我们利用 clang -rewrite-objc 命令,将题干的代码转化为如下代码:

  1. NSLog((NSString *)&__NSConstantStringImpl__var_folders_8k_cgm28r0d0bz94xnnrr606rf40000gn_T_Car_3f2069_mi_0, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("class"))));
  2. NSLog((NSString *)&__NSConstantStringImpl__var_folders_8k_cgm28r0d0bz94xnnrr606rf40000gn_T_Car_3f2069_mi_1, NSStringFromClass(((Class (*)(__rw_objc_super *, SEL))(void *)objc_msgSendSuper)((__rw_objc_super){(id)self, (id)class_getSuperclass(objc_getClass("Car"))}, sel_registerName("class"))));

从上方可以得出,调用 [Father class] 的时候,本质是在调用

objc_msgSendSuper(struct objc_super *super, SEL op, ...)

struct objc_super 的定义如下:

  1. struct objc_super {
  2. /// Specifies an instance of a class.
  3. __unsafe_unretained _Nonnull id receiver;
  4. /// Specifies the particular superclass of the instance to message.
  5. #if !defined(__cplusplus) && !__OBJC2__
  6. /* For compatibility with old objc-runtime.h header */
  7. __unsafe_unretained _Nonnull Class class;
  8. #else
  9. __unsafe_unretained _Nonnull Class super_class;
  10. #endif
  11. /* super_class is the first class to search */
  12. };

从定义可以得知:当利用 super 调用方法时,只要编译器看到super这个标志,就会让当前对象去调用父类方法,本质还是当前对象在调用,是去父类找实现,super 仅仅是一个编译指示器。但是消息的接收者 receiver 依然是self。最终在 NSObject 获取 isa 指针的时候,获取到的依旧是 self 的 isa,所以,我们得到的结果是:Son。

扩展一下: 看看下方的代码会输出什么?

  1. @interface Father : NSObject
  2. @end
  3. @implementation Father
  4. - (Class)class {
  5. return [Father class];
  6. }
  7. @end
  8. ---
  9. @interface Son : Father
  10. @end
  11. @implementation Son
  12. - (id)init {
  13. self = [super init];
  14. if (self) {
  15. NSLog(@"%@", NSStringFromClass([self class]));
  16. NSLog(@"%@", NSStringFromClass([super class]));
  17. }
  18. return self;
  19. }
  20. @end
  21. int main(int argc, const char * argv[]) {
  22. Son *foo = [[Son alloc]init];
  23. return 0;
  24. }
  25. ---输出:---
  26. Father
  27. Father

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Li_阴宅/article/detail/1022524?site
推荐阅读
相关标签
  

闽ICP备14008679号