29

私の理解が正しければ、Objective-C では、プロパティは getter と setter で自動的に合成され、インスタンス変数はプロパティ名として宣言され、アンダースコアが先頭に追加されます ( _ivar)。

したがって、このコード:

main.m

#import <Foundation/Foundation.h>
#import "hello.h"

int main(int argc, char *argv[])
{

    @autoreleasepool {

        Hello *hello = [[Hello alloc] init];
        NSLog(@"%@", hello.myString);

        return 0;

    }

}

こんにちは。

#import <Foundation/Foundation.h>

@interface Hello : NSObject
@property (copy, nonatomic) NSString *myString;
@end

こんにちは。

#import "hello.h"

@implementation Hello

-(Hello *)init
{

    if (self = [super init]) {
        _myString = @"Hello";
    }

    return self;

}

-(NSString *)myString
{
    return [NSString stringWithFormat:@"%@ %@", _myString, @"World"];
}

@end

次のようにコンパイルして実行できます。

bash-3.2$ clang -framework Foundation main.m hello.m -o hello
bash-3.2$ ./hello
2013-05-27 13:20:39.738 hello[23320:707] Hello World

myString プロパティを readonly に変更すると、次のようになります。

@property (readonly, copy, nonatomic) NSString *myString;

次に、コンパイルしようとすると、エラーが発生します。

hello.m:11:9: error: unknown type name '_myString'; did you mean 'NSString'?
        _myString = @"Hello";
        ^~~~~~~~~
        NSString

だから_myString定義されていません。コンパイラは、インスタンス変数 _myString を使用してプロパティを合成しませんでしたか? 自分で合成したときに機能するかどうかを見てみましょう。

hello.m の実装では:

@synthesize myString = _myString;

これで再び動作します:

bash-3.2$ clang -framework Foundation main.m hello.m -o hello
bash-3.2$ ./hello
2013-05-27 13:36:59.916 hello[24219:707] Hello World

readonlyだから、私の質問は、プロパティで使用するときにアンダースコアivarで自動的に合成されないのはなぜですか? それとも、このObjective-Cの仕組みを理解するのに完全に間違った道を進んでいますか?

正確に何が起こっているのか、その理由を本当に理解したいので、説明的な答えをいただければ幸いです。

前もって感謝します。

4

1 に答える 1