2013-06-20 5 views
5

commonConstructという名前のプライベートメソッドを定義することにより、さまざまな-(id)initのクラスのフレーバ、つまりinit、、initWithCoderなどでコードが重複しないようにしようとしています。Objective-C:同じ名前のプライベートスーパークラスメソッドへの意図しない呼び出しを避けるには?

このメソッドは、すべての初期メソッドのフレーバに共通して重い作業を行い、initコンストラクタによって呼び出されます。

私が今持っている問題は、それはすなわち.mファイルで宣言され、invisibleですが、初期化子ヘルパー(「commonConstruct」)のために同じ命名対流を使用して派生クラスで基本クラスは、派生クラスのcommonConstructを呼び出すということです、.hファイルではありません。

ただし、ランタイムは、オーバーロードされたcommonConstructを見つけて、それ自身のメンバー関数ではなく実行します。

各サブクラスの初期化ヘルパーに異なる名前を使用する以外の方法はありますか。

つまり、Objective-Cのメンバ関数を「非仮想」、つまり遅延(ランタイム)はなくコンパイル時バインディングにする方法はありますか?

+0

ここで 'commonConstruct'は定義されていますか? –

+0

commonConstructは各クラスの@implementationセクションで定義されています –

答えて

4

これを行うには、コンパイラが強制する方法はありません。メソッドは常に "仮想"であり、 "プライベート"メソッドの強制はありません。

一般的な解決策は、このように、メソッド名にクラス名を埋め込むことです:ロブMayoffのソリューションに加えて

@implementation Thing 

- (instancetype)init { 
    if (self = [super init]) { 
     [self Thing_commonInit]; 
    } 
    return self; 
} 

- (instancetype)initWithArg:(NSObject *)arg { 
    if (self = [super init]) { 
     [self Thing_commonInit]; 
     [self doSomethingWithArg:arg]; 
    } 
    return self; 
} 

- (void)Thing_commonInit { 
    ... 
} 
3

(私も使用している)あなたは、静的なC関数を使用できます。

@implementation Thing 
{ 
    id _privateIvar; 
} 

- (id)init 
{ 
    return commonInit([super init], nil); 
} 

- (id)initWithArgument:(id)argument 
{ 
    return commonInit([super init], argument); 
} 

static Thing *commonInit(Thing *self, id argument) 
{ 
    if (self == nil) 
     return nil; 
    self->_privateIvar = argument; 
    return self; 
} 

@end 

スタティック関数はシンボルを出力しないため、競合する可能性はありません。一般的なイニシャライザの名前をすべてcommonInitにすることができます。

+0

これは良い考えです。唯一の欠点は、インスタンスポインタを渡す必要があることです。メリットは、必要のないメッセージテーブルエントリを作成しないことです。 –

+0

@AraschHonarbachtはい、もちろんインスタンスポインタはインスタンスの初期化を行うために必要です。インスタンスメソッドを使用する場合の唯一の違いは、C関数のように明示的にではなく暗黙的に(セレクタとともに)渡されることです。 –

関連する問題