Почему я не вижу унаследованную переменную экземпляра в подклассе?

Я прочитал в книге «Основы программирования iOS» Мэтта Нойберга, что переменные экземпляра защищены, а это означает, что другие классы, за исключением подклассов этого, не могут их видеть.

У меня есть родительский класс A, в котором я определяю список ivar. (Являюсь)

@interface A ()

@end

@implementation A
{
     NSArray *list;
}

@end

Класс B расширяет A (B.h)

#import "A.h"

@interface B:A

@end

(B.m)

@interface B ()

@end

@implementation B

list = 
...

@end

Я хочу использовать список ivar в дочернем классе B, но компилятор не видит, что ссылка была объявлена ​​в родительском классе. Я пробовал явно использовать @protected, но это не сработало. Я не хочу показывать список ivar в общедоступном интерфейсе. Это внутренняя структура, которая является общим элементом всех подклассов. Как я могу это сделать?


person user2533198    schedule 28.05.2015    source источник
comment
Вы должны объявить переменную экземпляра в A.h, чтобы B мог ее видеть, и вы должны объявить ее как @protected   -  person Darren    schedule 28.05.2015


Ответы (2)


Переменные экземпляра, объявленные вне открытого интерфейса класса (другими словами, раздела @interface), по умолчанию являются закрытыми. Вы можете добавить к объявлению модификатор видимости, чтобы изменить видимость одного или нескольких ivars следующим образом:

@implementation A
{
     NSNumber *_ivarWithDefaultVisibility;

@protected
     NSArray *_list;
     NSString *_anotherIvarWithProtectedVisibility;
}

(Обратите внимание, что в соответствии с рекомендациями Apple по кодированию какао, имена ivar должны начинаться с символа подчеркивания.)

person jlehr    schedule 28.05.2015
comment
Этот блок @implementation находится в A.m файле, поэтому B не сможет его увидеть (компилятор не имеет доступа к A.m при сборке B.m). Вам пришлось бы объявить эти ivars в блоке @interface в A.h, если бы вы собирались сделать это таким образом. - person Rob Napier; 28.05.2015

Это необычный способ реализации защищенных свойств в ObjC. (@protected и @private очень редко используются в Какао.) Во-первых, используйте свойство, а не ivar. Это сделает его намного чище. Объявите это так:

A.h

@interface A : NSObject
// Public interface goes here
@end

A.m

// Declare the property in a class extension inside the implementation file.
// This is the idiomatic way to create a "private" property.
@interface A ()
@property (nonatomic, readwrite, strong) NSArray *list;
@end

A + protected.h

// Enumerated any methods that should be accessible to subclasses here.
// Properties are just a special way of defining methods.
// The word "Protected" is just a category name.

@interface A (Protected)
@property (nonatomic, readwrite, strong) NSArray *list;
@end

B.h

#import "A.h"   
@interface B : A
...
@end

B.m

#import "B.h"
#import "A+protected.h"

// ... now you can use self.list ...

Этот подход позволяет создавать любой «защищенный» метод, а не только свойства, а также является техникой, используемой для создания «дружественных» классов.

person Rob Napier    schedule 28.05.2015