Наследование переменных экземпляра в Objective-c - PullRequest
11 голосов
/ 15 декабря 2011

В Objective-c 2.0, почему подклассы должны ссылаться на переменные экземпляра в родительских классах, используя ключевое слово self?

Рассмотрим этот пример:

// a.h
@interface MyClass : NSObject
@property (nonatomic, retain) Object *myObject;
@end

// a.m
@implementation MyClass
@synthesize myObject;
@end


// b.h
@interface AnotherClass : MyClass
@end

// b.m
@implementation AnotherClass
- (void) someMethod {
    // error
    // Object *obj = myObject;

    // works
    // Object *obj = self.myObject;
}
@end

Ответы [ 2 ]

13 голосов
/ 15 декабря 2011

Вы на самом деле не определили переменную, вы только определили свойство (которое неявно определяет переменную, которая является закрытой).А так как свойство это просто метод, вам нужен точечный синтаксис.Обратите внимание, что self.property совпадает с [self property].

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

// a.h
@interface MyClass : NSObject {
    // Instance variables are "protected" by default, except if you
    // use @private or @public.
    Object *myObjectVar;
}

@property (nonatomic, retain) Object *myObject;
@end

// a.m
@implementation MyClass
@synthesize myObject = myObjectVar;
@end


// b.h
@interface AnotherClass : MyClass
@end

// b.m
@implementation AnotherClass
- (void) someMethod {
    // works
    Object *obj = myObjectVar;

    // works
    obj = self.myObject;

    // the same as self.myObject
    obj = [self myObject];
}
@end

Обратите внимание на разницу, когда вы назначаете : если вы назначаетеВаша переменная объект не сохраняется автоматически.Но оно сохраняется, если вы используете свойство:

myObjectVar = someObject; // not retained, old object not released!
self.myObject = someObject; // old object released, new object retained
[self setMyObject:someObject]; // same as the line above

Редактировать: Упомянуто, что синтезированные переменные экземпляра по умолчанию являются закрытыми, как отметил @Jason Coco.И @NSGod прав, что обычные переменные экземпляра защищены по умолчанию, а не public, исправили это.

8 голосов
/ 15 декабря 2011

Они этого не делают, если вы фактически объявляете переменную экземпляра в суперклассе, а не полагаетесь на способность новой среды выполнения синтезировать переменную экземпляра (в дополнение к синтезу методов доступа). См. Язык программирования Objective-C: Разница во времени выполнения для получения дополнительной информации о синтезе переменных экземпляра.

Например, чтобы иметь возможность напрямую ссылаться на переменную экземпляра, вам необходимо изменить следующее:

@interface MyClass : NSObject
@property (nonatomic, retain) Object *myObject;
@end

до:

@interface MyClass : NSObject {
// there is an implied @protected directive here
    Object *myObject;
}

@property (nonatomic, retain) Object *myObject;

@end

По умолчанию переменные экземпляра @protected, что означает, что класс и любые подклассы могут обращаться к переменным экземпляра напрямую. @protected ivars отличаются от @public ivars тем, что вы не можете получить к ним доступ, используя ->. @private ivars может быть доступен только классу, который их объявляет. См. Язык программирования Objective-C: Объем переменных экземпляра для получения дополнительной информации.

...