我正在阅读一本关于指南:
“如果一个类声明了一个与其超类不同的指定初始化器,则必须重写超类的指定初始化器以调用新的指定初始化器”
我的理解是,如果我从超类中继承了一个子类,并且我的子类具有与其超类不同的指定初始化器,那么我在子类中必须重写超类的指定初始化器,并在其中调用子类的指定初始化器。
这是真的吗?我们必须一直这样做吗?谢谢。
我正在阅读一本关于指南:
“如果一个类声明了一个与其超类不同的指定初始化器,则必须重写超类的指定初始化器以调用新的指定初始化器”
我的理解是,如果我从超类中继承了一个子类,并且我的子类具有与其超类不同的指定初始化器,那么我在子类中必须重写超类的指定初始化器,并在其中调用子类的指定初始化器。
这是真的吗?我们必须一直这样做吗?谢谢。
@justin说得基本正确。
在 Objective-C 中,方法是可以被继承的。这意味着如果超类有一个初始化方法 (初始化器只是一种方法),而你的子类没有覆盖它,则你的子类将继承该超类的初始化方法。这意味着人们总是可以在你的子类对象上调用超类的初始化方法 (继承和子类型多态的基本后果)。但这可能不是你预期的结果。超类的初始化方法可能无法完成你的类所需的所有初始化工作。
这就是为什么你应该重写超类的初始化方法。如果你不希望人们在你的类上使用该初始化方法,那么你应该在该初始化方法中抛出异常。否则,你应该重写它来为你的类做任何适当的初始化工作。
// implicitly adds a designated initializer. -init is still valid:
@interface MONObject : NSObject
- (instancetype)initWithString:(NSString *)pString;
@end
Ex.2:
// redefines the designated initializer. -init is not valid:
@interface MONObject : NSObject
// MONObject's designated initializer
- (instancetype)initWithString:(NSString *)pString;
@end
Ex.3:
// define all designated initializers:
@interface MONObject : NSObject
// MONObject's designated initializers:
- (instancetype)init;
- (instancetype)initWithString:(NSString *)pString;
@end
编辑
在评论中澄清问题。
当您只是覆盖超类声明的初始化程序时:
这是真的吗?我们必须一直这样做吗?
除非您的类有初始化要执行,否则不需要显式地覆盖超类的指定初始化程序。
您的实例将被初始化为具有零化内存。
给定:
@interface MONObject : NSObject
- (instancetype)initWithString:(NSString *)pString;
@property (nonatomic, copy, readwrite) NSString * string;
@end
@implementation MONObject
// if @property string should be initialized to nil, you may omit -[MONObject init]
// otherwise, initialize self here:
- (instancetype)init
{
// call super's designated initializer:
self = [super init];
// test it:
if (nil == self) return nil;
// init your state
_string = @"(null)";
return self;
}
- (instancetype)initWithString:(NSString *)pString;
{
// call super's designated initializer:
self = [super init]; // << will not call -[MONObject init]
// test it:
if (nil == self) return nil;
// init your state
_string = pString.copy;
return self;
}
@end
这基本上是说,如果一个类有一个 iniWithSomethingDomething
,那么最好做一个
self = [super initWithSomethingSomeThing:......]
在你自己的初始化器中
-(id) initWithName:(NSString *)aName
{
self = [super init];
if (self){
[self setName:aName];
}
return self;
}
然后在覆盖父类时调用它
-(id) init
{
return [self initWithName: @""];
}