В чем разница между вызовом self.myInstanceVariable и непосредственно myInstanceVariable? - PullRequest
2 голосов
/ 01 мая 2009

Месяц назад я читал об этом. Я не уверен, но я думаю, что если я вызову self.myInstanceVariable, то он автоматически использует getter / setters, но если я, например, вызову напрямую myInstanceVariable = @ "Foo", то я бы обошел любой getter / setter, действительно, очень плохо. Правильно / неправильно?

РЕДАКТИРОВАТЬ: я пробовал это в XCode.

Реализация выглядит так:

@implementation Test
@synthesize name;

+ (Test*)testWithName:(NSString*)name {
    Test* test = [self alloc];
    test.name = name;
    return [test autorelease];
}

- (void)setName:(NSString*)newName {
    NSLog(@"SETTER CALLED!!");
    if(name != newName) {
        [name release];
        name = [newName retain];
    }
}

- (NSString*)name {
    NSLog(@"GETTER CALLED!!");
    return name;
}

- (void)doWrongThing {
    NSString *x = name;
    NSLog(@"doWrongThing: %@", x);
}
- (void)doRightThing {
    NSString *x = self.name;
    NSLog(@"doRightThing: %@", x);
}

Тестовый код выглядит так:

Test *t = [Test testWithName:@"Swanzus Longus"];
//NSLog(@"%@", t.name);
[t doWrongThing];
[t doWrongThing];
[t doWrongThing];

[t doRightThing];

Итак, после запуска этого кода в другом методе (я только что использовал существующий проект;)), я получил такой вывод в консоли:

2009-05-01 19:00:13.435 Demo[5909:20b] SETTER CALLED!!
2009-05-01 20:19:37.948 Demo[6167:20b] doWrongThing: Swanzus Longus
2009-05-01 20:19:37.949 Demo[6167:20b] doWrongThing: Swanzus Longus
2009-05-01 20:19:37.949 Demo[6167:20b] doWrongThing: Swanzus Longus
2009-05-01 20:19:37.950 Demo[6167:20b] GETTER CALLED!!
2009-05-01 20:19:37.965 Demo[6167:20b] doRightThing: Swanzus Longus

Как вы видите, вы ДОЛЖНЫ использовать self.instanceVariableName, чтобы использовать методы получения и установки (или вы делаете вызов в скобках, тоже работает).

Предупреждение о путанице: вы должны использовать self только в том случае, если вы взломали метод объекта, из которого вы хотите получить доступ к переменной экземпляра. Снаружи, когда вы вызываете someObjectPointer.someInstanceVariable, он автоматически получает доступ к получателям и установщикам (да, я тоже это пробовал).

Просто подумал, что кому-то будет интересно небольшое тематическое исследование;)

Ответы [ 4 ]

9 голосов
/ 01 мая 2009

Это правильно. Если вы напрямую используете переменную, минуя метод получения / установки, вы можете создавать ошибки. Получатель / установщик может нести ответственность за сохранение и / или освобождение объекта, а также за другие вещи. Это может привести к сбоям / утечке памяти и т. Д.

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

3 голосов
/ 01 мая 2009

Джесси обладает хорошим пониманием (+1 к вам, сэр).

Единственное обстоятельство, при котором я бы рассмотрел явный вызов основной переменной-члена напрямую (таким образом, минуя метод получения / установки), - это когда я сам написал метод получения / установки, и точно знаю, что это такое, а что нет, В 99% случаев я просто инициализирую член в своем конструкторе.

2 голосов
/ 02 мая 2009

Просто прочитайте документацию

Во-первых, это неправильно

Test* test = [self alloc];

правильное значение

Test* test = [[self alloc] init];

Во-вторых, если вы напишите

@synthesize name;

Методы

- (void)setName:(NSString*)newName
- (NSString*)name

будет сгенерировано (!! точка-синтаксис - это просто синтаксис-сахар !!) автоматически

В-третьих, когда вы пишете

myvar.itInstanceVariable

переводится как

[myvar itInstanceVariable]

и

myvar.itInstanceVariable = newValue

переводится как

[myvar setItInstanceVariable:newValue]

О вашем комментарии, когда вы декларируете свою собственность таким образом

@property(nonatomic, retain) MyType *myVar;

и напишите в реализации

@ synthesize myVar

создает два метода

- (MyType*)myVar {
     return myVar;
}

- (void)setMyVar:(MyType*)newVar {
    if (myVar != newVar) {
       [myVar release];
       myVar = [newVar retain];
    }
}

так что вам не нужно беспокоиться о повторной обработке / освобождении

1 голос
/ 01 мая 2009

Да, синтаксис свойства вызывает установщик. Практически во всех случаях это именно то, что вам нужно, так как по умолчанию оно правильно обрабатывает много памяти. Кроме того, имя свойства, имя ivar и имена получателя / установщика также могут быть разными, поэтому вы можете найти случаи, когда они не похожи на self.myInstanceVar.

Кроме того, как примечание, вы можете знать, а можете и не знать об этом, но нет смысла синтезировать свойство, если вы все равно собираетесь написать все методы доступа.

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