1.什么是全能初始化方法?
提供必要信息的初始化方法。
2.先搞一个例子
@interface YXRectangle : NSObject
@property (nonatomic,readonly) float width;
@property (nonatomic,readonly) float height;
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
@end
@implementation YXRectangle
//全能初始化方法
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height
{
self = [super init];
if (self) {
_width = width;
_height = height;
}
return self;
}
@end
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height
这个方法就是全能初始化方法。其他的初始化方法都应该调用这个方法来创建对象。
3.所以我们还要至少要复写已经有的初始化方法,比如init方法
@interface YXRectangle : NSObject
@property (nonatomic,readonly) float width;
@property (nonatomic,readonly) float height;
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height;
@end
@implementation YXRectangle
- (instancetype)init{
return [self initWithWidth:500 height:500];
}
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height
{
self = [super init];
if (self) {
_width = width;
_height = height;
}
return self;
}
@end
这样不管使用者怎么创建都能通过这个全能初始化方法正常创建。
4.那他的子类也一个全能初始化方法,而且要调用父类的全能初始化方法,以维系调用链。
比如我们创建一个正方形的子类YXSquare
@interface YXSquare : YXRectangle
- (instancetype)initWithDimension:(CGFloat)dimension;
@end
@implementation YXSquare
- (instancetype)initWithDimension:(CGFloat)dimension
{
return [super initWithWidth:dimension height:dimension];
}
@end
5.但是如果使用者继续使用父类的全能初始化方法呢,这样就有可能出现宽高不等的正方形。
所以还应该阻止使用者直接调用父类的全能初始化方法
@interface YXSquare : YXRectangle
- (instancetype)initWithDimension:(CGFloat)dimension;
@end
@implementation YXSquare
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height{
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Must be use initWithDimension :instead" userInfo:nil];
}
- (instancetype)initWithDimension:(CGFloat)dimension
{
return [super initWithWidth:dimension height:dimension];
}
@end
6.如果使用者还是用init来创建呢,这样还是调用父类中的init方法,还是有可能出现长宽不等的情况,所以还应该复写一下init方法
@interface YXSquare : YXRectangle
- (instancetype)initWithDimension:(CGFloat)dimension;
@end
@implementation YXSquare
- (instancetype)initWithWidth:(CGFloat)width height:(CGFloat)height{
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Must be use initWithDimension :instead" userInfo:nil];
}
- (instancetype)initWithDimension:(CGFloat)dimension
{
return [super initWithWidth:dimension height:dimension];
}
-(instancetype)init{
return [self initWithDimension:500];
}
@end
7.如果有两种全能初始化方法呢?比如UIView,有从code中加载的全能初始化方法initWithCoder之类的。
覆写它,然后在其中调用父类的全能初始化方法。
8.总结
- 在类中提供一个全能初始化方法,并于文档中说明,其他方法都应该调用此方法
- 若全能初始化方法与父类不同,则需覆写超类中的对应方法
- 如果超类的初始化方法不适用于子类,那么应该覆写这个超类的方法,并在其中抛出异常