在Java和C++中,this总是指的是当前实例地址,而在静态方法也就是类方法中,是不可以使用this的。在Objectvie-C中,self是既可以出现在实例方法中,也可以出现在类方法中,并且在不同的方法中有不同的意义。在实例方法中self代表实例地址,而在类方法中,self代表该Class对象地址。
#import <Foundation/Foundation.h> @interface X : NSObject - (void)printSelf; + (void)printSelf; @end @implementation X - (void)printSelf { NSLog(@"-printSelf:%@", self); } + (void)printSelf { NSLog(@"+printSelf:%@", self); } @end int main(int argc, const char * argv[]) { @autoreleasepool { X *x = [[X alloc] init]; [X printSelf]; [x printSelf]; } return 0; }
上面的代码分别使用实例方法和类方法打印self,下面是控制台的输出:
可以看到实例方法确实打印出了实例地址,而类方法只打印了一个类名X,但是通过汇编代码并观察寄存器rdi(rdi中包含的就是传递给NSLog的self值)的值,我们可以看到
SelfTest`+[X printSelf]: 0x100000e30 <+0>: pushq %rbp 0x100000e31 <+1>: movq %rsp, %rbp 0x100000e34 <+4>: subq $0x10, %rsp 0x100000e38 <+8>: leaq 0x219(%rip), %rax ; @"+printSelf:%@" 0x100000e3f <+15>: movq %rdi, -0x8(%rbp) 0x100000e43 <+19>: movq %rsi, -0x10(%rbp) 0x100000e47 <+23>: movq -0x8(%rbp), %rsi -> 0x100000e4b <+27>: movq %rax, %rdi 0x100000e4e <+30>: movb $0x0, %al 0x100000e50 <+32>: callq 0x100000ef6 ; symbol stub for: NSLog 0x100000e55 <+37>: addq $0x10, %rsp 0x100000e59 <+41>: popq %rbp 0x100000e5a <+42>: retq
rdi中的值为:
这和实例方法打印的值不同。
实际上,对于main函数中调用的类方法:
[X printSelf]
完全可以替换为下面的形式:
[[X class] printSelf]
[X class]返回的就是类X的class实例,而+printSelf方法中的self指代的就是这个class对象的地址。
时间: 2024-09-29 16:40:59