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;

}

程序打印以下内容: x 等于 100

“x”不是私有实例变量并且对象“b”不能访问,因为“x”是在超类“a”的实现文件中声明的,而“b”是一个子类?

书中说“子类直接访问的实例变量必须在接口部分而不是在实现部分中声明......在实现部分中声明或合成的实例变量是私有实例变量,不能直接访问子类。”

真的被这个弄糊涂了。

4

2 回答 2

3

方法setXprintX是公开且可见的,因此可以在 的实例上调用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这种间接访问是一种面向对象的编程概念,称为封装。

于 2013-07-10T04:52:28.563 回答
0

Ivars@protected默认有属性,意味着子类可以访问它们。要将 ivar 声明为私有,@private请在 ivar 声明之前使用属性:

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

如果您在@implementationsection 中声明您的 ivars,它们对子类可见的唯一方法是在您的子类中导入 .m 文件,但您不能使用它们,因为它们是私有的。

或者根本不使用 ivars,因为 Objective-C 属性现在会自动创建 ivars。如果您需要私有属性,可以通过 .m 文件中的匿名类别声明它,如下所示:

@interface MyClass ()

@property (nonatomic) NSInteger x;

@end

更新: 我想我明白什么让你感到困惑。公共和受保护的 ivars由子类继承,可以作为子类的实例变量直接访问,无需使用子类的访问器方法。

于 2013-07-10T04:50:47.093 回答