Objective-C中的self与LLVM Clang新引入的instancetype

咱们知道,大部分面向对象语言对于一个类的成员方法都有一个隐含的参数。在C++、Java、C#和JavaScript中是this,而在Objective-C中则是self。固然,因为Objective-C++要彻底兼容标准C++,所以关键字不能与C++有所冲突,因此用了self。编程


可是,Objective-C中的self与C++、Java等编程语言中的还有一点不一样——Objective-C中的self能够用于类方法,而不只仅是成员方法,这点C++、Java等都没法作到。好比:安全

@interface MyClass : NSObject

+ (id)createMyObject;

@end

@implementation MyClass

- (id)init
{
    self = [super init];
    
    NSLog(@"Hello, world");
    
    return self;
}

+ (id)createMyObject
{
    MyClass *mc = [[self alloc] init];
    
    return [mc autorelease];
}

@end

咱们看到,上述代码片断中MyClass类的createMyObject类方法中经过self来调用NSObject的类方法alloc。这里,self指向了createMyObject这个消息所发送给的类。当咱们用[MyClass createMyObject]这句语句时,createMyObject中的self其实就指示了MyClass类自己。所以,能够直接用self来调用类方法alloc。框架


而后利用这个特性,咱们结合LLVM Clang新引入的instancetype能够编写出兼容性更强,更灵活方便的工厂方法。下面先介绍一下instancetype编程语言


instancetype其实跟id差很少,可是它跟id不一样的是,它表示一个与当前类相兼容的类型,而id则是一个通用的Objective-C对象类型引用类型。所以,若是咱们要在一个类方法中返回类型为自身类型的对象,那么返回类型能够写instancetype。而上述代码片断彻底符合这个要求,所以咱们能够作以下改写:this

@interface MyClass : NSObject

+ (instancetype)createMyObject;
- (void)dummyMethod;

@end

@implementation MyClass

- (id)init
{
    self = [super init];
    
    NSLog(@"Hello, world");
    
    return self;
}

+ (instancetype)createMyObject
{
    MyClass *mc = [[self alloc] init];
    
    return [mc autorelease];
}

- (void)dummyMethod
{
    
}

@end

这样一来,咱们若是这么用:[[MyClass createMyObject] dummyMethod]会很是安全。由于createMyObject方法所返回的对象可确保是与MyClass类相兼容的。spa

这里须要注意的是instancetype只能用做为返回类型,不容许做为参数或用于定义临时变量。code

咱们下面将提供一个结合self特性与instancetype特性的工厂方法:对象

@interface MyClass : NSObject

+ (instancetype)createMyObject;
- (void)dummyMethod;

@end

@interface MySubClass : MyClass

@end

@implementation MyClass

- (id)init
{
    self = [super init];
    
    NSLog(@"Hello, world");
    
    return self;
}

+ (instancetype)createMyObject
{
    MyClass *mc = [[self alloc] init];
    
    return [mc autorelease];
}

- (void)dummyMethod
{

}

@end

@implementation MySubClass

- (id)init
{
    self = [super init];
    
    NSLog(@"Hi, world!");
    
    return self;
}

- (void)dummyMethod
{
    NSLog(@"I am a child.");
}

@end

你能够调用[[MySubClass createMyObject] dummyMethod],能够看看输出结果。blog


此时,你会有个疑问,我直接用MyClass *myObj = [[MySubClass alloc] init];不也同样能够嘛,须要那么复杂吗?接口

固然,C++、Java等编程语言都是这么作的。而Objective-C目前有两种状态,一种是MRC(Manual Reference Count),另外一种是ARC(Auto Reference Count)。这两种模式对于实例建立而言是不同的。前者建立完了以后,须要调用release,然后者则不须要。所以,咱们经过上述讲解的经过类方法来建立autorelease对象来有效地屏蔽应用层接口的统一性问题。咱们看到Apple本身在iOS7.0开始可用的框架都大量用了此种方法。这样,经过模版自动生成出来的代码不论是在MRC下仍是在ARC下都能正常工做。

相关文章
相关标签/搜索