Objective-Cの初期化メソッドについて

225 views
Skip to first unread message

m_yukio

unread,
Feb 13, 2009, 10:22:14 PM2/13/09
to cocoa-dev-japan
こんにちは、村上です。あるセミナーで出た質問です。
おそらく、C++的なクラスは構造体という考えから出た疑問だと思います。
Objective-Cでは、サブクラスを実装する場合、init初期化メソッドは、以下のようにコーディングすると説明されていると思います。

- (id)init
{
if ((self = [super init])) {
// サブクラス固有の初期化処理を記述
}
return self;
}

質問された方は、これだと最上位クラス(NSObject)のinitメソッドが実行されるので、サブクラス固有領域は、どう確保されるの?と疑問にも
たれたようです。

その時は、Objective-Cでは、selfはインスタンス変数とメソッドを管理する領域と関係ずれられ、NSObjectのallocとinit
で用意されるので、問題ないのでは?と、思いましたが、後で、では、どのタイミングで、サブクラスのインスタンス変数とメソッドがselfに組み込まれ
るのは、私自身も疑問に思ってきました。
そこで、以下のような、テスト・プログラムを作成して、実行してみました。

#import <Foundation/Foundation.h>

@interface Demo : NSObject
{
int instVal;
}
- (id)init;
- (int)instVal;
- (void)setInstVal:(int)val;
@end

@implementation Demo

- (id)init
{
if ([[self class] isKindOfClass:[NSObject class]]) {
NSLog(@"1) self is NSObject");
}
if ([[self class] isKindOfClass:[Demo class]]) {
NSLog(@"1) self is Demo");
}

if ((self = [super init])) {
instVal = 0;
}

if ([[self class] isKindOfClass:[NSObject class]]) {
NSLog(@"2) self is NSObject");
}
if ([[self class] isKindOfClass:[Demo class]]) {
NSLog(@"2) self is Demo");
}

NSLog(@"self = %@", self);

return self;
}

- (int)instVal
{
return instVal;
}

- (void)setInstVal:(int)val
{
instVal = val;
}

@end

int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

Demo *demo = [[Demo alloc] init];
NSLog(@"demo = %@", demo);

if ([[demo class] isKindOfClass:[NSObject class]]) {
NSLog(@"3) self is NSObject");
}
if ([[demo class] isKindOfClass:[Demo class]]) {
NSLog(@"3) self is Demo");
}

[pool drain];
return 0;
}

結果は以下の感じでした。

2009-02-14 12:09:16.271 objc[383:10b] 1) self is NSObject
2009-02-14 12:09:16.273 objc[383:10b] 2) self is NSObject
2009-02-14 12:09:16.274 objc[383:10b] self = <Demo: 0x1034d0>
2009-02-14 12:09:16.274 objc[383:10b] demo = <Demo: 0x1034d0>
2009-02-14 12:09:16.275 objc[383:10b] 3) self is NSObject

selfとサブクラスの関係は、コンパイラでサブクラスに対してallocとinitしているので、関係づけられるのでしょうか?
NSLogでselfの内容を印字したら、サブクラスとなっていました。

予想と違っていたのは、isKindOfClassでのクラスの判定ですが、サブクラスだと上手くいきませんでした。
これは、私のコードが間違っているのでしょうか?

wang

unread,
Feb 14, 2009, 9:17:28 AM2/14/09
to cocoa-dev-japan
if ([[demo class] isKindOfClass:[NSObject class]]) {
ここが間違っています。


[demo isKindOfClass:[NSObject class]]

でいいです。

[demo class]ではClass型になるので常にClass型のオブジェクトのクラスを比較していることになっています。

m_yukio

unread,
Feb 15, 2009, 8:48:38 AM2/15/09
to cocoa-dev-japan
指摘ありがとうございます。

> [demo isKindOfClass:[NSObject class]]

修正しましたら。上手く行きました。

Objective-Cの書籍を読んだところ、allocでインスタンス変数は0に初期化されているという記述を見つけました。
つまり、ある型でallocメソッドで領域確保された際に、そのクラスのインスタンス変数とメソッドの関連はつけられている。initは、クラスの初期
化処理を記述するだけ、ということですね。
冷静に考えてみれば、そのインスタンスのinitメソッドが呼ばれるという事自体、その段階で、そのインスタンスのクラスにinitメソッドがあるとい
う関連が存在しているという事なので、当たり前ですね。
Reply all
Reply to author
Forward
0 new messages