Переменная класса, определенная в @implementation, а не @interface?
Я новичок в Objective-C, но мне интересно, что я на самом деле не видел в другом месте.
Может ли кто-нибудь сказать мне, какая разница между частной переменной, объявленной в блоке @interface
, против переменной, объявленной в блоке @implementation
вне методов класса, i.e:
@interface Someclass : NSObject {
NSString *forExample;
}
@end
против.
@implementation Someclass
NSString *anotherExample;
-(void)methodsAndSuch {}
@end
Кажется, что обе переменные (forExample
, anotherExample
) одинаково доступны во всем классе, и я не могу найти разницу в их поведении. Вторая форму также называется переменной экземпляра?
Ответы
Ответ 1
Последнее не определяет переменную экземпляра. Скорее, он определяет глобальную переменную в файле .m. Такая переменная не уникальна или не является частью любого экземпляра объекта.
Такие глобалы имеют свои применения (примерно эквивалентные статические элементы С++, например, хранение экземпляра singleton), но обычно вы определяете их в верхней части файла перед директивой @implementation.
Ответ 2
Они очень разные! Тот, что находится в @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;
Затем вы можете использовать методы класса для взаимодействия с переменной, и это явно относится к классу (в отличие от конкретного экземпляра или глобального).
Ответ 3
Если вы объявляете переменную в разделе @implementation, вы фактически создаете глобальную переменную, видимую повсюду (в каждом методе в вашем приложении).
Членские переменные могут быть объявлены только в разделе @interface. Они доступны только в самом классе.
Ответ 4
Частный блок, объявленный внутри блока @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
Ответ 5
Чтобы быть ясным, никогда не объявляйте IBOutlet как глобальный var (в реализации), если вы используете его для локализованных nibs/xibs.
Я потратил несколько часов на то, чтобы понять, почему розетка подключается только в одном из локализованных наконечников в любой момент времени.
Спасибо за этот вопрос и ответы!