Objective-C语法之self
2017-07-26 16:46
134 查看
在实现Objective-C类的方法时, 我们可以在方法内部用self关键字来引用当前对象或者当前类, 使对象或类自己作为消息的接收者.
用代码来说明, 定义一个类ClassA:
我们来实现它的方法:
可以看到, 在实现instanceMethodB时, 给self发送了instanceMethodA消息, 此时, self就引用着”当前对象”, 因为instanceMethodA是个对象方法, 它的接收者必须是一个对象.
同理, 在classMethodB中, 给self发送了classMethodA消息, 由于classMethodA是个类方法, 其接收者必须是一个类, 所以此时self就引用着”当前类”, 即ClassA.
总结起来就是一句话: self引用着当前消息的接收者.
延伸:
我们经常会给一个类设计一个或多个构造方法, 来快速地创建对象. 在构造方法内部, 我们也应该尽量使用self关键字, 而不是直接使用类名, 这是为了构造方法在子类中也能返回正确的子类对象, 而不是父类.
用代码来说明, 在ClassA中定义一个构造方法:
实现构造方法, 先看第一种方式(不推荐):
创建一个ClassB, 继承自ClassA. 看如下的测试代码:
我们用ClassB调用anObject方法, 返回的对象依然是ClassA类型, 这显然就达不到我们本来的目的了.
再看第二种实现方式(推荐写法):
此时, 再次运行:
这就达到我们预期的效果了.
另外, 在很多地方还能看到第三种实现方式, 用[self class]代替self:
这其实和第二种方式是等效的, 因为无论是self或者[self class], 此时代表的东西是一样的, 都是”当前类”.
最后建议, 在设计初始化方法或者构造方法时, 应该用instancetype作为返回类型, 这有助于类型安全, 详情可参阅我的这篇博文.
用代码来说明, 定义一个类ClassA:
@interface ClassA : NSObject - (void)instanceMethodA; - (void)instanceMethodB; + (void)classMethodA; + (void)classMethodB; @end
我们来实现它的方法:
- (void)instanceMethodA { } - (void)instanceMethodB { // 调用实例方法, 此时self代表"当前对象"或"当前实例" [self instanceMethodA]; } + (void)classMethodA { } + (void)classMethodB { // 调用类方法, 此时self代表"当前类" [self classMethodA]; // 效果等同于[ClassA classMethodA]; }
可以看到, 在实现instanceMethodB时, 给self发送了instanceMethodA消息, 此时, self就引用着”当前对象”, 因为instanceMethodA是个对象方法, 它的接收者必须是一个对象.
同理, 在classMethodB中, 给self发送了classMethodA消息, 由于classMethodA是个类方法, 其接收者必须是一个类, 所以此时self就引用着”当前类”, 即ClassA.
总结起来就是一句话: self引用着当前消息的接收者.
延伸:
我们经常会给一个类设计一个或多个构造方法, 来快速地创建对象. 在构造方法内部, 我们也应该尽量使用self关键字, 而不是直接使用类名, 这是为了构造方法在子类中也能返回正确的子类对象, 而不是父类.
用代码来说明, 在ClassA中定义一个构造方法:
@interface ClassA : NSObject + (instancetype)anObject; // 构造方法 @end
实现构造方法, 先看第一种方式(不推荐):
+ (instancetype)anObject { // 直接使用类名调用alloc return [[ClassA alloc] init]; }
创建一个ClassB, 继承自ClassA. 看如下的测试代码:
id obj1 = [ClassA anObject]; NSLog(@"%@", NSStringFromClass([obj1 class])); // 输出ClassA id obj2 = [ClassB anObject]; NSLog(@"%@", NSStringFromClass([obj2 class])); // 输出ClassA
我们用ClassB调用anObject方法, 返回的对象依然是ClassA类型, 这显然就达不到我们本来的目的了.
再看第二种实现方式(推荐写法):
+ (instancetype)anObject { // 使用self调用alloc return [[self alloc] init]; }
此时, 再次运行:
id obj2 = [ClassB anObject]; NSLog(@"%@", NSStringFromClass([obj2 class])); // 输出ClassB
这就达到我们预期的效果了.
另外, 在很多地方还能看到第三种实现方式, 用[self class]代替self:
+ (instancetype)anObject { return [[[self class] alloc] init]; }
这其实和第二种方式是等效的, 因为无论是self或者[self class], 此时代表的东西是一样的, 都是”当前类”.
最后建议, 在设计初始化方法或者构造方法时, 应该用instancetype作为返回类型, 这有助于类型安全, 详情可参阅我的这篇博文.
相关文章推荐
- objective-c 基础语法和习题 / self 的用法
- Objective-C—self 、super、点语法、成员变量的作用域、@property和@synthesize、id
- [Objective-C]-02-set get语法.类方法.self关键字与点语法
- Objective-C Copy语法(二)对于我们自定义对象Copy以及[self class]相关的错误
- Objective-C语法之self
- Objective-C语法快速参考
- Objective-C语法之代码块(block)的使用
- 14,Objective-C语法之代码块(block)的使用
- Objective-C语法之基本数据类型
- Objective-C语法之代码块(block)的使用
- Objective-C的self.用法的一些总结
- Objective-C语法快速参考
- Objective-C 的 self 和 super 详解 (用简单程序说明问题)
- Objective-C语法之动态类型(isKindOfClass, isMemberOfClass,id)等
- Objective-C字面量语法总结
- Objective-C语法之KVC使用
- #Objective - C NSString的常用语法点总结
- 如何在Objective-C中实现链式语法
- Objective-C语法之常用数据的那些事儿(二)
- Objective-C语法之集合对象的那些事儿(九)