我很难通过示例了解私有实例变量。在阅读了私有实例变量之后,我去了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;
}
该程序打印以下内容: x等于100
不是“x”私有实例变量,对象“b”不可访问,因为“x”在superClass“a”的实现文件中声明,而“b”是子类?
书中说“子类直接访问的实例变量必须在接口部分声明,而不是在实现部分...在实现部分声明或合成的实例变量是私有实例变量而不是可以通过子类直接访问。“
真的很困惑。
答案 0 :(得分:3)
方法setX
和printX
是公开且可见的,因此可以在ClassB
的实例上调用。由于它们是公开的,因此ClassB
也可以调用它们,就像这样。
@implementation ClassB
- (void)fig {
[self setX];
}
@end
不能完成的是ClassB
直接访问值x。像这样:
@implementation ClassB
- (void)foo {
NSLog(@"x is now %i", x);
}
@end
ClassB
没有直接访问x
,但它通过超类方法间接访问x
。这种间接访问是一种面向对象的编程概念,称为封装。
答案 1 :(得分:0)
Ivars默认具有@protected
属性,意味着子类可以访问它们。要将ivar声明为private,请在ivar声明之前使用@private
属性:
@interface ClassA : NSObject
{
@private
int x;
}
如果你在@implementation
部分声明你的ivars,它们对子类可见的唯一方法是在子类中导入.m文件,但你不能使用它们,因为它们是私有的。 / p>
或者根本不使用ivars,因为Objective-C属性现在自动创建ivars。如果您需要私有属性,可以通过.m文件中的匿名类别声明它,如下所示:
@interface MyClass ()
@property (nonatomic) NSInteger x;
@end
<强>更新强> 我想我明白了你的困惑。公共和受保护的ivars由子类继承,可以直接作为子类的实例变量访问,不需要使用子类中的访问器方法。