Objective-C里关于self和self super init, 其本质究竟是什么?

豆丁微信公众号
君,已阅读到文档的结尾了呢~~
刨根问底Objective-C Runtime
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
刨根问底Objective-C Runtime
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='http://www.docin.com/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口Objective-C 中的 Meta-class 是什么? - 文章 - 伯乐在线
& Objective-C 中的 Meta-class 是什么?
在这篇文章中,我关注的是 Objective-C 中的一个陌生的概念—— meta-class。在 Objective-C 中的每个类都有一个相关联的 meta-class,但是你很少会直接使用 meta-class,他们仍旧保持着神秘的面纱。我们从在运行时创建一个类开始。通过查看 “class pair”,我会解释 meta-class 是什么,同时也会谈谈在 Objective-C 中的对象或者类相关的一些一般主题。
在运行时创建一个类
下面的代码在运行时创建了一个 NSError 的子类同时为它添加了一个方法:
Class newClass =
objc_allocateClassPair([NSError class], "RuntimeErrorSubclass", 0);
class_addMethod(newClass, @selector(report), (IMP)ReportFunction, "v@:");
objc_registerClassPair(newClass);
<div class="crayon-num" data-line="crayon-5a77d<div class="crayon-num crayon-striped-num" data-line="crayon-5a77d<div class="crayon-num" data-line="crayon-5a77d<div class="crayon-num crayon-striped-num" data-line="crayon-5a77d
Class newClass =&&&&objc_allocateClassPair([NSError class], "RuntimeErrorSubclass", 0);class_addMethod(newClass, @selector(report), (IMP)ReportFunction, "v@:");objc_registerClassPair(newClass);
添加的方法使用叫 ReportFunction 的函数作为实现,定义如下:
void ReportFunction(id self, SEL _cmd)
NSLog(@"This object is %p.", self);
NSLog(@"Class is %@, and super is %@.", [self class], [self superclass]);
Class currentClass = [self class];
for (int i = 1; i & 5; i++)
NSLog(@"Following the isa pointer %d times gives %p", i, currentClass);
currentClass = object_getClass(currentClass);
NSLog(@"NSObject's class is %p", [NSObject class]);
NSLog(@"NSObject's meta class is %p", object_getClass([NSObject class]));
123456789101112131415
void ReportFunction(id self, SEL _cmd){&&&&NSLog(@"This object is %p.", self);&&&&NSLog(@"Class is %@, and super is %@.", [self class], [self superclass]);&&&&&Class currentClass = [self class];&&&&for (int i = 1; i & 5; i++)&&&&{&&&&&&&&NSLog(@"Following the isa pointer %d times gives %p", i, currentClass);&&&&&&&&currentClass = object_getClass(currentClass);&&&&}&&&&&NSLog(@"NSObject's class is %p", [NSObject class]);&&&&NSLog(@"NSObject's meta class is %p", object_getClass([NSObject class]));}
表面上来看,非常简单。在运行时创建一个类只需要这三步:
1、为 “class pair” 创建存储空间(使用 objc_allocateClassPair)。
2、为这个类添加所需的 methods 和 ivars(我已经使用 class_addMethod 添加过一个方法了)。
3、注册这个类,然后就可以使用了(使用 objc_registerClassPair)。
然后,中级问题是:“class pair” 是什么?函数 objc_allocateClassPair 只返回了一个值:这个 class。这一对中的另一个在哪?(译注:pair 有 “一对,一双” 的意思)
我敢肯定你已经猜到了另一半就是 meta-class(就是这篇文章的标题),但是要解释那是什么和你为什么需要它,我需要介绍一些在 Objective-C 中的关于对象和类的背景知识。
把一个数据结构变为对象需要什么?
每个对象都有一个类。这是面相对象概念的基础知识,但在 Objective-C 中不是这样,它(译注:class)同样是这个数据的一部分。每个可以被当成对象的数据结构都在恰当的位置有一个指向一个类的指针。
在 Objective-C,一个对象的类由它的 isa 指针决定。isa 指针指向这个对象的 Class。
事实上,在 Objective-C 中的对象的定义看起来像这样:
typedef struct objc_object {
typedef struct objc_object {&&&&Class isa;} *id;
这就是说:任何结构体只要以一个指向 Class 结构的指针开始的就可以被当成是 objc_object。
在 Objective-C 中的对象的一个重要的特性是,你可以向它们发送消息:
[@"stringValue"
writeToFile:@"/file.txt" atomically:YES encoding:NSUTF8StringEncoding error:NULL];
[@"stringValue"&&&&writeToFile:@"/file.txt" atomically:YES encoding:NSUTF8StringEncoding error:NULL];
你可以这么做是因为,当你向一个 Objective-C 的对象(像这里的 NSCFString)发送消息的时候,runtime 沿着对象的 isa 指针找到了这个对象的 Class(这里是 NSCFString 的类)结构体。 Class 结构体中包含了一个这个类的方法列表和一个指向父类的指针,用于查找继承的方法。
关键点是 Class 结构体中定义了你可以向一个对象发送的消息。
meta-class 是什么?
现在,你可能已经知道,在 Objective-C 中一个 Class 也是一个对象。这就意味着你也可以向一个 Class 发送消息。
NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];
NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];
这里,向 NSString 类发送了 defaultStringEncoding。
可以这么做是因为在 Objective-C 中每个 Class 它自己同样也是个对象。也就是说 Class 结构体必须以 isa 指针开始,然后就可以在二进制兼容(binary compatible)我上面介绍的 objc_object 结构了,接着下一个字段必须是一个指向它的父类的指针(要是类就是基类就是 nil)。
,定义一个类有好几种方法,主要依赖于你正在运行的 runtime 的版本。但,是的,都是由一个 isa 字段开始然后是 superclass 字段。
typedef struct objc_class *C
struct objc_class {
Class super_
/* 以下依赖于 runtime 的具体实现 …… */
typedef struct objc_class *Class;struct objc_class {&&&&Class isa;&&&&Class super_class;&&&&/* 以下依赖于 runtime 的具体实现 …… */};
然而,为了让我们在 Class 上调用一个方法,Class 的 isa 指针必须指向一个 Class 结构体,并且那个 Class 结构体必须包含我们可以在那个 Class 上调用的方法的列表。
这就引出了 meta-class 的定义:meta-class 是 Class 对象的类(the meta-class is the class for a Class object)。
简单来说:
当你向一个对象发送消息,就在那个对象的方法列表中查找那个消息。
当你想一个类发送消息,就再那个类的 meta-class 中查找那个消息。
meta-class 是必须的,因为它为一个 Class 存储类方法。每个类都必须有一个唯一的 meta-class,因为每个 Class 都有一个可能不一样的类方法。
meta-class 的类是什么?
meta-class,如之前的 Class,同样是个对象。这就意味着你也可以在它上面调用方法。自然的,这就意味着它也必须有一个类(译注:isa 指针)。
所有的 meta-class 使用它们基类的 meta-class (继承层次中最顶层的 Class 的 meta-class)作为它们自己的类。这就是说所有继承自 NSObject 的类(大部分的类),以 NSObject 的 meta-class 作为自己的 meta-class 的类。
遵循这个规则,所有的 meta-class 使用基类的 meta-class 作为他们的类,任何基类的 meta-class 将会是他们自己(它们的 isa 指向他们自己)。这就是说 NSObject 的 meta-class 的 isa 指针指向它们自己(是自己的一个实例)。
class 和 meta-class 的继承
和 Class 以 super_class 指针指向它的父类的方法一样,meta-class 以 super_class 指针指向 Class 的 super_class 的 meta-class。(译注:这句话有点绕,就是 super-class 一个指向 Class 的父类,一个指向 meta-class 的父类。Class 是一般对象的类型,meta-class 是 Class 的类型。)
进一步来讲,基类的 meta-class 设置 super_class 指针指向基类自己。
这个继承层次的结果就是,所有在这个继承层次中的的实例,类和 meta-class 都继承了基类的层次。
对于所有在 NSObject 层次中的实例,类和 meta-class,这就意味着所有 NSObject 的实例方法都是有效的。对于类和 meta-class,所有 NSObject 的类方法也同样是有效的。
所有这些在字面上相当让人困惑。Greg Parker 已经把实例,类,meta-class 还有他们的超类以非常棒的图解的方式聚合在一起,展示他们是如何在一起工作的。
用实验验证这点
为了验证这些,让我们看看在我文章开头提供的 ReportFunction 的输出。这个函数的目的是顺着 isa 指针打引出它找到的。
要运行 ReportFunction,我们需要为这个动态创建的类创建一个实例,然后在上面调用这个方法。
id instanceOfNewClass =
[[newClass alloc] initWithDomain:@"someDomain" code:0 userInfo:nil];
[instanceOfNewClass performSelector:@selector(report)];
[instanceOfNewClass release];
id instanceOfNewClass =&&&&[[newClass alloc] initWithDomain:@"someDomain" code:0 userInfo:nil];[instanceOfNewClass performSelector:@selector(report)];[instanceOfNewClass release];
因为没有这个方法的声明,所以我使用 performSelector: 调用这个方法,这样编译器就不会输出警告了。
现在 ReportFunction 会沿着 isa 指针告诉我们这个对象使用了哪些类,meta-class 和 meta-class 的类。
获取一个对象的类:ReportFunction 使用 object_getClass 跟随 isa 指针,因为 isa 指针是一个类中一个受保护的成员变量(你不能直接访问其他对象的 isa 指针)。ReportFunction 没有以类方法的形式这样调用,因为在 Class 对象上调用类方法不会返回 meta-class,而是再次返回 Class 对象(所以 [NSString class] 会返回 NSString 的类而不是 NSString 的 meta-class)。
这个是程序运行后的结果(省去了 NSLog 的前缀)。
This object is 0x.
Class is RuntimeErrorSubclass, and super is NSError.
Following the isa pointer 1 times gives 0x
Following the isa pointer 2 times gives 0x
Following the isa pointer 3 times gives 0x7fff
Following the isa pointer 4 times gives 0x7fff
NSObject's class is 0x7fff
NSObject's meta class is 0x7fff
This object is 0x.Class is RuntimeErrorSubclass, and super is NSError.Following the isa pointer 1 times gives 0xFollowing the isa pointer 2 times gives 0xFollowing the isa pointer 3 times gives 0x7fffFollowing the isa pointer 4 times gives 0x7fffNSObject's class is 0x7fffNSObject's meta class is 0x7fff
看看通过递归的查看 isa 的地址:
the object is address 0x.
the class is address 0x.
the meta-class is address 0x.
the meta-class’s class (i.e. the NSObject meta-class) is address 0x7fff.
the NSObject meta-class’ class is itself.
地址的值不是很重要,只是演示了上面讨论的从类到 meta-class 到 NSObject 的 meta-class 的过程。
meta-class 是 Class 对象的类。每个 Class 都有个不同的自己的 meta-class(因此每个 Class 都可以有一个自己不同的方法列表)。也就是说每个类的 Class 不完全相同。
meta-class 总是会保证 Class 对象会有从基类继承的所有的的实例和类方法,加上之后继承的类方法。如从 NSObject 继承的类,就意味着在所有的 Class(和 meta-class)对象中定义了所有从 NSObject 继承的实例和协议方法。
所有的 meta-class 使用基类的 meta-class(NSObject 的 meta-class 用于继承自 NSObject 的类)作为他们自己的类,包括在运行时自己定义的基础的 meta-class。
可能感兴趣的话题
关于伯乐在线博客
在这个信息爆炸的时代,人们已然被大量、快速并且简短的信息所包围。然而,我们相信:过多“快餐”式的阅读只会令人“虚胖”,缺乏实质的内涵。伯乐在线内容团队正试图以我们微薄的力量,把优秀的原创文章和译文分享给读者,为“快餐”添加一些“营养”元素。
新浪微博:
推荐微信号
(加好友请注明来意)
&#8211; 好的话题、有启发的回复、值得信赖的圈子
&#8211; 分享和发现有价值的内容与观点
&#8211; 为IT单身男女服务的征婚传播平台
&#8211; 优秀的工具资源导航
&#8211; 翻译传播优秀的外文文章
&#8211; 国内外的精选文章
&#8211; UI,网页,交互和用户体验
&#8211; 专注iOS技术分享
&#8211; 专注Android技术分享
&#8211; JavaScript, HTML5, CSS
&#8211; 专注Java技术分享
&#8211; 专注Python技术分享
& 2018 伯乐在线Objective-C里关于self和super, 其本质究竟是什么?-self和super的区别 _星空生活网
你现在浏览的是: & > &
Objective-C里关于self和super, 其本质究竟是什么?
Objective-C里关于self和super, 其本质究竟是什么?
OS开发中;%@&quot,经常会用到self和super,self不难理解是自己的一个指针,可以通过NSLog(@&quot
以以前 oop 语言的经验;self &#39,会使用 objc_msgSend 的函数,先看下 objc_msgSend 的函数定义, class is %@&, [self class]),先只关注 objc_msgSend 和 objc_msgSendSuper 两个方法。当使用 [self setName] 调用时。这里只关注这个 self。super 是个啥?super 并不是隐藏的参数?按照以前oop语言的经验,这里应该会输出:  self &#39; s class is PersonMe super &#39; s class is Person  但是编译运行后,可以发现结果是:  self &#39;s class is PersonMe super &#39,它和 self 指向的是相同的消息接收者,拿上面的代码为例,super 告诉编译器; - (void) setName,没什么问题. These functions are declared in &#47; class is %@&quot,这么看起来是很容易理解的。  在 Objective-C 中的类实现中经常看到这两个关键字 ”self” 和 ”super”,以以前 oop 语言的经验,拿 c++ 为例.  objc_msgSendSuper_stret sends a message with a data-structure return value to the superclass of an instance of a class.  可以看到会转成调用上面 4 个方法中的一个,由于 _stret 系列的和没有 _stret 的那两个类似,它只是一个“编译器指示符”,会打出来这两个的super&#39.  objc_msgSend_stret sends a message with a data-structure return value to an instance of  a class.  objc_msgSendSuper sends a message with a simple return value to the superclass of anobjc&#47;objc-runtime.  objc_msgSend sends a message with a simple return value to an instance of a class, and the arguments. You can use these functions to dynamically invoke methods from your own plain C code, or to use argument forms not permitted by NSObject’s perform… s class is PersonMe  self 的 class 和预想的一样,这些代码看起来很好理解:(NSUInteger) @end @implementation PersonMe - (void) setName:(NSString*) yourName andAge:(NSUInteger) age { [self setAge:age].h; [super setName,不论是用 [sel......
父类指针啊,这个有啥可问的?
objective-c里有没有可以实现类似java这种arraylist&hashmap&k,v&&... :
json格式: [{&id&:1,&name&:&zhangsan:},{&id&:2,&name&...
objective c 可以定义 变量名为 id 吗 :
可以,编译器不会认为这是一个错误,但不建议这样做。 因为在 Objcective-C 中,id 本身...
(1) The coordinates of the three points A,B C on t... :
第一个为等腰三角形,选B 第二个为1
你可能感兴趣的内容?5被浏览3,077分享邀请回答stackoverflow.com上找解答了,分享下,我英文不大好.我理解的大体意思是: super是个编译器的指令符号,只是告诉编译器在执行的时候,去调谁的方法.原文如下.如有不妥,请拍砖提醒.When encountering the keyword super and a method call on it, the compiler generates a different call - objc_msgSendSuper*() instead of the usual objc_msgSend*().objc_msgSendSuper*() calls get an argument of type objc_super* instead of objc_object*:struct objc_super {
C};So, objc_super* values aren't special instances, they have to be used with the specialobjc_msgSendSuper*() functions.Thus, as Alex says, just call -description directly on super - its value is meaningless outside of the context its in unless you specifically use it with a runtime function like objc_msgSendSuper(). 41 条评论分享收藏感谢收起11 条评论分享收藏感谢收起写回答问题补充&&
本页链接:
以以前 oop 语言的经验;self &#39,会使用 objc_msgSend 的函数,先看下 objc_msgSend 的函数定义, class is %@&, [self class]),先只关注 objc_msgSend 和 objc_msgSendSuper 两个方法。当使用 [self setName] 调用时。这里只关注这个 self。super 是个啥?super 并不是隐藏的参数?按照以前oop语言的经验,这里应该会输出:  self &#39; s class is PersonMe super &#39; s class is Person  但是编译运行后,可以发现结果是:  self &#39;s class is PersonMe super &#39,它和 self 指向的是相同的消息接收宅拿上面的代码为例,super 告诉编译器; - (void) setName,没什么问题. These functions are declared in &#47; class is %@&quot,这么看起来是很容易理解的。  在 Objective-C 中的类实现中经常看到这两个关键字 ”self” 和 ”super”,以以前 oop 语言的经验,拿 c++ 为例.  objc_msgSendSuper_stret sends a message with a data-structure return value to the superclass of an instance of a class.  可以看到会转成调用上面 4 个方法中的一个,由于 _stret 系列的和没有 _stret 的那两个类似,它只是一个“编译器指示符”,会打出来这两个的super&#39.  objc_msgSend_stret sends a message with a data-structure return value to an instance of  a class.  objc_msgSendSuper sends a message with a simple return value to the superclass of anobjc&#47;objc-runtime.  objc_msgSend sends a message with a simple return value to an instance of a class, and the arguments. You can use these functions to dynamically invoke methods from your own plain C code, or to use argument forms not permitted by NSObject’s perform… s class is PersonMe  self 的 class 和预想的一样,这些代码看起来很好理解:(NSUInteger) @end @implementation PersonMe - (void) setName:(NSString*) yourName andAge:(NSUInteger) age { [self setAge:age].h; [super setName,不论是用 [sel......余下全文>>
xiangjuan314 &
&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;&#8226;
父类指针啊,这个有啥可问的?
猜你感兴趣

我要回帖

更多关于 ios self super 的文章

 

随机推荐