Objective-C语法之self

在实现Objective-C类的方法时, 我们可以在方法内部用self关键字来引用当前对象或者当前类, 使对象或类自己作为消息的接收者.
用代码来说明, 定义一个类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作为返回类型, 这有助于类型安全, 详情可参阅我的这篇博文.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值