これに対するかなり確実な解決策の1つは、静的cメソッドを使用して初期化を行うことです。すべての有効なcは有効なobjective-cです。
したがって、たとえば、CustomSuperclass.h:
#import <Foundation/Foundation.h>
@interface CustomSuperclass : NSObject
@property (nonatomic) NSUInteger integer;
@end
CustomSuperclass.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
CustomSubclass.h:
#import "CustomSuperclass.h"
@interface CustomSubclass : CustomSuperclass
@end
CustomSubclass.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
IBは、インスタンス化されたコードが呼び出される/呼び出されるはずの場所を呼び出すため、サブクラスUIView
にとって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()
解決策を具体的に尋ねました。