在@implementation而不是@interface定义的类变量?

时间:2010-04-03 14:35:56

标签: objective-c

我是Objective-C的新手,但我对其他地方没见过的东西感到好奇。

有人能告诉我在@interface块声明的私有变量与在类方法之外的@implementation块内声明的变量之间有什么区别,即:

@interface Someclass : NSObject {

 NSString *forExample;

}

@end

VS

@implementation Someclass

 NSString *anotherExample;

-(void)methodsAndSuch {}

@end

似乎两个变量(forExampleanotherExample)在整个班级中都可以同等地访问,我无法真正发现他们的行为有所不同。第二种形式是否也称为实例变量?

6 个答案:

答案 0 :(得分:29)

后者没有定义实例变量。相反,它是在.m文件中定义一个全局变量。这样的变量不是任何对象实例的唯一或部分。

这样的全局变量有其用途(大致相当于C ++静态成员;例如存储单例实例),但通常你会在@implementation指令之前在文件的顶部定义它们。

答案 1 :(得分:23)

他们非常不同! @implementation中的一个是全局变量,并非每个实例都是唯一的。想象一下,这两个变量都有访问器,以明显的方式编写。然后,这里显示了行为的差异:

Someclass* firstObject = [[Someclass alloc] init];
Someclass* secondObject = [[Someclass alloc] init];

//forExample is an instance variable, and is unique to each instance.
[firstObject setForExample:@"One"];
[secondObject setForExample:@"Two"];
NSLog(@"%@",[firstObject forExample]); //Result: "One"
NSLog(@"%@",[secondObject forExample]); //Result: "Two"

//anotherExample is a global variable, and is NOT unique to each instance.
[firstObject setAnotherExample:@"One"];
[secondObject setAnotherExample:@"Two"];
NSLog(@"%@",[firstObject anotherExample]); //Result: "Two" (!)
NSLog(@"%@",[secondObject anotherExample]); //Result: "Two"

//Both instances return "Two" because there is only ONE variable this time.
//When secondObject set it, it replaced the value that firstObject set.

如果您正在寻找这种行为,最好使用类变量,如下所示:

static NSString* yetAnotherExample = nil;

然后你可以使用类方法与变量进行交互,它显然是特定于类的(而不是特定于实例的或全局的)。

答案 2 :(得分:5)

如果在@implementation部分中声明一个变量,那么实际上是在创建一个全局变量,在任何地方都可见(在应用程序的每个方法中)。

成员变量只能在@interface部分声明。它们只能在课堂上访问。

答案 3 :(得分:3)

@implementation块中声明的私有块在我看来是危险的,与其他OOP概念相比,例如Java的。它看起来像成员变量,但有点静态。

新手程序员很容易被它愚弄。我写了一个测试程序,并对这个行为感到惊讶。

@interface SomeClass : NSObject
{
    NSString *forExample;
}

- (void) set:(NSString *)one another:(NSString *)another;
- (void)print;

@end

实现:

#import "SomeClass.h"

@implementation SomeClass

NSString *anotherExample;

- (void) set:(NSString *)one another:(NSString *)another
{
    forExample = one;
    anotherExample = another;
}

- (void)print{
    NSLog(@"One = %@, another = %@", forExample, anotherExample);
}

@end

测试:

- (void)testClass {
    SomeClass * s1 = [SomeClass new];
    [s1 set:@"one one" another:@"one another"];
    SomeClass *s2 = [SomeClass new];
    [s2 set:@"two one" another:@"two another"];
    [s1 print];
    [s2 print];
}

输出是,

One = one one, another = two another
One = two one, another = two another

答案 4 :(得分:0)

为了清楚起见,如果您将IBOutlet用于本地化的nibs / xibs,那么永远不要将IBOutlet声明为全局var(在实现中)。

我花了几个小时来确定为什么插座在任何给定时间只能在一个本地化的笔尖中连接。

感谢您提出这个问题和答案!

答案 5 :(得分:0)

使用代码段来说明成员变量和全局变量之间的区别:

@implementation MyClass {
  // It is an ivar, or called member variable
  // Can NOT be initialized when defined.
  // Can be accessed with `self->_i`
  int _i; 
}

- (instancetype)init {
    if (self = [super init]) {
       _i = 2; // should be initialized before being used.
    }
    return self;
}

int i = 9; // Global variable, and can be initialized when defined.
- (void)myFun {
    NSLog(@"%i, %i", self->_i, i);
}

@end


// Another file

extern int i;
NSLog(@"%i", i);