为什么使用instancetype?

有人可以向我解释(简单来说)为什么在Objective-C中使用instancetype

 - (instancetype) init { self = [super init]; if (self) { // Custom initialization } return self; } 

这是为了提高类型安全性。

回到过去,初始化者只返回了id (任何对象)类型的对象。

使用普通的初始化程序(以“init”,“alloc”或“new”开头),这通常不是问题。 编译器会自动推断它返回的类型,因此将对象的任何方法调用限制为该类的实例方法。

但是,这静态便利初始化程序或“工厂方法”的问题,它们不一定遵循相同的命名约定 – 因此它无法应用相同的类型安全性。

这意味着对于这样的类:

 @interface Foo : NSObject +(id) aConvenienceInit; @end 

编译器会接受这样的代码:

 NSArray* subviews = [Foo aConvenienceInit].subviews; 

为什么? 因为返回的对象可以是任何对象,所以如果您尝试访问UIView属性 – 没有类型安全来阻止您。

但是,现在使用instancetype ,您获得的结果是您给定实例的类型。 现在有了这段代码:

 @interface Foo : NSObject +(instancetype) aConvenienceInit; @end ... NSArray* subviews = [Foo aConvenienceInit].subviews; 

您将收到编译器警告,指出属性subviews不是Foo*的成员:

虽然值得注意的是,如果您的方法以“alloc”,“init”或“new”开头,编译器会自动将返回类型从id转换为instancetype – 但尽管如此,尽管如此,使用instancetype是一个很好的习惯。


有关详细信息,请参阅instancetype上的Apple文档 。

想象一下两个类:

 @interface A : NSObject - (instancetype)init; @end @interface B : A @end 

Ainit方法inheritance到B 但是,在这两个类中,该方法具有不同的返回类型。 在A ,返回类型是A ,在B ,返回类型是B

没有其他方法可以正确声明初始化程序的返回类型。 请注意,大多数具有类的编程语言甚至没有构造函数的返回类型,因此它们完全避免了这个问题。

这就是为什么Obj-C 需要 instancetype的原因,当然它也可以在初始化器之外使用。