2013-07-10 2 views
1

Мне сложно понять частные переменные экземпляра на примере. Прочитав о частных переменных экземпляра, я пошел в Xcode и попытался проверить, как они работают.Понимание переменной частного экземпляра

В книге, которую я читаю, говорится, что если вы объявите переменную экземпляра в файле реализации суперкласса, переменная экземпляра будет закрыта и недоступна для подклассов.

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

/** SuperClass interface file**/ 
#import <Foundation/Foundation.h> 

@interface ClassA : NSObject 

-(void) setX; 
-(void) printX; 

@end 

/**SuperClass implementation file **/ 
#import "ClassA.h" 

@implementation ClassA 
{ 
    int x; 
} 

-(void) setX 
{ 
    x = 100; 
} 

-(void) printX 
{ 
    NSLog(@" x is equal to %i", x); 
} 

@end 

/** interface file of subclass **/ 
#import "ClassA.h" 

@interface ClassB : ClassA 

@end 



/**Main file **/ 
#import "ClassA.h" 
#import "ClassB.h" 


int main(int argc, const char * argv[]) 
{ 

    @autoreleasepool 


    { 

     ClassA * a; 
     a = [[ClassA alloc] init]; 

     ClassB * b; 
     b = [[ClassB alloc] init]; 


     [b setX]; 
     [b printX]; 



    } 
    return 0; 

}

Программа печатает следующее: х равна 100

не является «х» частной переменной экземпляра и недоступны объекта «б», потому что «х» объявляется в файле реализации суперкласса «a», а «b» - подкласс?

В книгах говорится, что «переменные экземпляра, которые должны быть доступны непосредственно подклассом, должны быть объявлены в разделе интерфейса, а не в разделе реализации ... Переменные экземпляра, объявленные или синтезированные в разделе реализации, являются частными переменными экземпляра и являются не доступными напрямую подклассами ».

Действительно смущен этим.

+0

Я думаю, что '@implementation ClassA {int x; } 'часть не должна компилироваться. Это действительно так, как ваш код? – ThomasW

+0

Интересно, он компилируется. Я никогда не видел эту конструкцию раньше. – ThomasW

+0

Я просто скопировал это прямо из Xcode. Что вы видите не так с этой частью? – Brosef

ответ

0

По умолчанию атрибут Ivars имеет атрибут @protected, значит подклассы могут получить к ним доступ. Для того, чтобы объявить Ивар как частные, используйте @private атрибут до объявления Ивара:

@interface ClassA : NSObject 
{ 
@private 
    int x; 
} 

Если вы объявляете ваш Ивар в @implementation разделе, единственный способ для них, чтобы быть видимыми подклассы импортировать файл .m в подклассе, но вы не можете использовать их, потому что они частные.

Или вообще не используйте ivars, так как объекты Objective-C теперь создают ивары автоматически. Если вам нужна частная собственность, вы можете объявить через анонимную категорию в .m файл, как это:

@interface MyClass() 

@property (nonatomic) NSInteger x; 

@end 

UPDATE: Я думаю, я понимаю, что вас смущает. Публичные и защищенные ivars: унаследованы подклассами и могут быть доступны непосредственно как переменные экземпляра подкласс, не нужно использовать методы доступа из подкласса.

+0

Спасибо за ответ. Я смущен текстом из книги и как мой пример относится к нему. В книгах говорится, что «переменные экземпляра, которые должны быть доступны непосредственно подклассом, должны быть объявлены в разделе интерфейса, а не в разделе реализации ... Переменные экземпляра, объявленные или синтезированные в разделе реализации, являются частными переменными экземпляра и не являются напрямую доступный по подклассам ». Не мой подкласс просто получил доступ к переменной частного экземпляра? – Brosef

+0

@somid, ваш подкласс не имел прямого доступа к переменной частного экземпляра. Доступ был косвенным. – ThomasW

+0

@thomasW Я все еще новичок в этом. Как выглядит пример подкласса, пытающегося получить доступ к переменной экземпляра? – Brosef

3

Методы setX и printX являются общедоступными и видимыми и поэтому могут быть вызваны по экземпляру ClassB. Поскольку они являются общедоступными, они также могут быть вызваны ClassB, вот так.

@implementation ClassB 

- (void)fig { 
    [self setX]; 
} 

@end 

Что не может быть сделано для ClassB для прямого доступа значение х.Как это:

@implementation ClassB 

- (void)foo { 
    NSLog(@"x is now %i", x); 
} 

@end 

ClassB не имеет прямой доступ кx, но она имеет косвенную доступ к x через методы суперкласса. Этот косвенный доступ представляет собой концепцию объектно-ориентированного программирования, известную как инкапсуляция.

+0

Итак, если вы объявляете переменную экземпляра в файле интерфейса, ее публикация. Если вы объявляете переменную экземпляра в файле реализации, ее частную. Но какая разница, когда дело доходит до подкласса. Очевидно, что в приведенном выше примере подкласс все еще имел доступ к переменной частного экземпляра. – Brosef

+0

Вы также можете сделать переменную экземпляра private с помощью '@ private', как в ответе @ KyrDunenkoff. Подкласс не имеет прямого доступа к переменной экземпляра, но имеет * косвенный * доступ, используя методы суперкласса. – ThomasW

+0

Может ли объект «b» из класса B косвенно изменить значение «x» на использование объекта «a»? Например, если этот метод приведен ниже в реализации суперкласса ClassA, и мы написали [classB setX: 15] в основном файле. Будет ли объект «a» читать 15 как новое значение для «x»? @implementation ClassA - (void) комплектX: (int) xVal { x = xVal; } – Brosef

Смежные вопросы