Переменная класса, определенная в @implementation, а не в @interface? - PullRequest
40 голосов
/ 03 апреля 2010

Я новичок в Objective-C, но мне любопытно что-то, что я не видел, адресованное где-либо еще.

Может ли кто-нибудь сказать мне, в чем разница между закрытой переменной, объявленной в блоке @interface, и переменной, объявленной в блоке @implementation вне методов класса, то есть:

@interface Someclass : NSObject {

 NSString *forExample;

}

@end

против

@implementation Someclass

 NSString *anotherExample;

-(void)methodsAndSuch {}

@end

Кажется, что обе переменные (forExample, anotherExample) одинаково доступны во всем классе, и я не могу найти разницу в их поведении. Вторая форма также называется переменной экземпляра?

Ответы [ 6 ]

30 голосов
/ 03 апреля 2010

Последний не определяет переменную экземпляра. Скорее, он определяет глобальную переменную в файле .m. Такая переменная не является уникальной или является частью какого-либо экземпляра объекта.

Такие глобальные переменные имеют свое применение (примерно эквивалентные статические члены C ++; например, хранение экземпляра-одиночки), но обычно вы определяете их в верхней части файла перед директивой @implementation.

23 голосов
/ 03 апреля 2010

Они очень разные! Значение в @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;

Затем вы можете использовать методы класса для взаимодействия с переменной, и она явно специфична для класса (в отличие от конкретного или глобального).

5 голосов
/ 03 апреля 2010

Если вы объявляете переменную внутри секции @implementation, вы фактически создаете глобальную переменную, видимую повсюду (в каждом методе в вашем приложении).

Переменные-члены могут быть объявлены только в разделе @interface.Они доступны только в самом классе.

3 голосов
/ 14 февраля 2014

Закрытый блок, объявленный внутри блока @implementation, кажется мне опасным по сравнению с другими концепциями ООП, например, Джава. Это похоже на переменную-член, но немного статично.

Начинающий программист может легко обмануть его. Я пишу тестовую программу и удивляюсь поведению.

@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
0 голосов
/ 14 июня 2018

Используйте фрагмент кода, чтобы определить разницу между переменной-членом и глобальной переменной:

@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);
0 голосов
/ 01 марта 2013

Просто для ясности, никогда не объявляйте IBOutlet как глобальную переменную (в реализации), если вы используете его для локализованных nibs / xibs.

Я потратил несколько часов, чтобы понять, почему розетка подключается только к одному из локализованных перьев в любой момент времени.

Спасибо за этот вопрос и ответы!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...