一个相当可靠的解决方案是使用静态 c 方法进行初始化。毕竟所有有效的c都是有效的objective-c。
例如,CustomSuperclass.h:
#import <Foundation/Foundation.h>
@interface CustomSuperclass : NSObject
@property (nonatomic) NSUInteger integer;
@end
自定义超类.m:
#import "CustomSuperclass.h"
@implementation CustomSuperclass
@synthesize integer = _integer;
static void initializeInstance(CustomSuperclass *self) {
self.integer = 9;
}
-(id)init{
if ((self = [super init])){
initializeInstance(self);
}
return self;
}
@end
自定义子类.h:
#import "CustomSuperclass.h"
@interface CustomSubclass : CustomSuperclass
@end
自定义子类.m:
#import "CustomSubclass.h"
@implementation CustomSubclass
// Obviously we would normally use (CustomSubclass *self), but we're proving a point with identical method signatures.
void initializeInstance(CustomSuperclass *self) {
self.integer = 10;
}
-(id)init{
if ((self = [super init])){
// We won't call this classes `initializeInstance()` function.
// We want to see if this one overrides it's superclasses version.
}
return self;
}
@end
现在如果你运行这样的代码:
CustomSuperclass *instanceOfSuperclass = [[CustomSuperclass alloc] init];
NSLog(@"superclass integer:%i", instanceOfSuperclass.integer);
CustomSubclass *instanceOfSubclass = [[CustomSubclass alloc] init];
NSLog(@"subclass integer:%i", instanceOfSubclass.integer);
你会看见:
superclass integer:9
subclass integer:9
如果子类的版本initializeInstance()
是子类使用的版本(调用时[super init]
),那么子类整数将为 10。这证明了initializeInstance()
超类的方法没有被子类的版本覆盖(至少在超类的范围内) .
编辑以回应评论:
我发布了这个答案及其解决方案,不是因为我认为这是解决问题的最佳方法,而是因为它符合问题的规范。问题本质上是,“我如何强制动态语言以静态方式运行,这样我就不必遵循正常的命名/初始化约定?”
处理这种情况的最佳方法是让您的类有一个指定的初始化程序,每个初始化程序都会调用该初始化程序。喜欢:
/* Designated initializer */
-(id)initWithFile:(NSString *)file andURL:(NSURL *)url{
if ((self = [super init])){
_url = url;
_file = file;
// Initialization of new instance code here.
}
return self;
}
-(id)initWithFile:(NSString *)file{
return [self initWithFile:file andURL:nil];
}
-(id)initWithURL:(NSURL *)url{
return [self initWithFile:nil andURL:url];
}
指定的初始化器几乎适用于所有情况。它们对于UIView
子类来说有点麻烦,因为 IBUIView
会initWithCoder:
在实例化代码UIView
将/应该调用的地方initWithFrame:
调用。在这种情况下,可能会编写一个通用方法以在调用后完成[super initWith...]
以减少代码重复。
覆盖通用初始化方法的名称可能会遇到问题。对于大多数人来说,这是通过默默无闻获得一点安全性的地方,例如:
-(void)initialize_CustomUIView{
// Common init tasks
}
-(id)initWithFrame:(CGRect)frame{
if ((self = [super initWithFrame:frame])){
[self initialize_CustomUIView];
}
return self;
}
-(id)initWithCoder:(NSCoder *)aDecoder{
if ((self = [super initWithCoder:aDecoder])){
[self initialize_CustomUIView];
}
return self;
}
-(id)init{
if ((self = [super init])){
[self initialize_CustomUIView];
}
return self;
}
但是再次,您特别询问了如何禁止自己覆盖通用初始化方法,因此是static void initializeInstance()
解决方案。