web-dev-qa-db-ja.com

ObjC実装ファイルで宣言されたインスタンス変数

WWDC ARCの紹介ビデオを見ていて、AppleエンジニアがStackの例について話したときに、ObjCでこれまで見たことのないものを見ました。

次のコードは、ARCのスタックの例に使用されました。

@implementation Stack 
{ 
    // instance variable declared in implementation context
    NSMutableArray *_array; 
}

- (id)init 
{
   if (self = [super init])
      _array = [NSMutableArray array];
   return self;
}

- (void)Push:(id)x 
{
   [_array addObject:x];
}

- (id)pop 
{
   id x = [_array lastObject];
   [_array removeLastObject];
   return x;
}

@end

@ implementationディレクティブの直後に宣言されたインスタンス変数に注意してください。

ここで驚いたのは、静的変数でなくても、インスタンス変数を実際に実装ファイルで宣言できることです。私の質問は次のようになります:

  • これは、SDK for iOS 5で導入された新しい構成ですか、それとも長い間可能でしたか?
  • オブジェクトの外部でインスタンス変数にアクセスしない場合は、実装でインスタンス変数を宣言することをお勧めしますか? @privateディレクティブを使用するよりもずっとクリーンなようです。
47

これは確かに新しい言語機能であり、(単にプロパティを宣言してコンパイラーにivarを生成させるのではなく)ivarを宣言する必要がある場合は、良い方法です。理論上、ヘッダーファイルはクラスのパブリックインターフェイスのみを公開する必要があります。他のすべては実装に属します。

1つの注意点は、実装ファイルのivarがサブクラスに表示されないことです。サブクラス化する必要のあるセッターとゲッターを手動で生成した場合は、少し厄介になることがあります。

40
Seamus Campbell

実装内でiVarを宣言することは、間違いなくObjective Cの新しい構成です。xcode4.2を使用し、ビルド設定でLLVMコンパイラーを選択する必要があります。アイデアは、ヘッダーファイルをよりクリーンに保つことです。この例のように、中括弧内にivarをリストできます。

@implementation MyClass {    
  int var1;
  int var2;
}

Rahulによって与えられた答えは実際には正しくありませんが、コンパイラーによって静的であると見なされるだろうと彼が言う方法で変数をデラレすることができます。おそらく彼がそれらを使用したケースでは、それは問題ではありませんでした。

18
David Temple

私はObjective Cを初めて使用しましたが、ヘッダーでivarを宣言する方法は非常に奇妙であることがわかりました。これは、パブリックヘッダーでオブジェクトの内部状態を宣言することを意味し、カプセル化の概念に反しています。

たとえば、iPadを所有しているとします。 Appleは、あなたがIPadを開いてこじ開けたり、内部の要素をいじったりすることを望んでいません。それらが何かを変更したい場合、IPadはそれを変更できる設定を持っています。

同様に、他のプログラマーに自分のオブジェクトのivarを見させたくありません。それは私のオブジェクトの内部状態です。内部状態にアクセスしてほしい場合は、そのプロパティを宣言します。

したがって、他の言語と同様に、実装ファイル内でivarを非表示にし、ヘッダーでそれらを宣言しません。

ヘッダーでivarを宣言すると、非常に奇妙な印象を受けます。これらのivarは実装固有であり、ヘッダーファイルの一部であってはなりません。

3
Leander