为什么使用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
A
的init
方法inheritance到B
但是,在这两个类中,该方法具有不同的返回类型。 在A
,返回类型是A
,在B
,返回类型是B
没有其他方法可以正确声明初始化程序的返回类型。 请注意,大多数具有类的编程语言甚至没有构造函数的返回类型,因此它们完全避免了这个问题。
这就是为什么Obj-C 需要 instancetype
的原因,当然它也可以在初始化器之外使用。