在Objective-C中“ @private”是什么意思?


Answers:


186

这是可见性修饰符 -意味着声明为的实例变量@private只能由同一类的实例访问。子类或其他类不能访问私有成员。

例如:

@interface MyClass : NSObject
{
    @private
    int someVar;  // Can only be accessed by instances of MyClass

    @public
    int aPublicVar;  // Can be accessed by any object
}
@end

另外,为了澄清起见,方法在Objective-C中始终是公共的。但是,有多种方法可以“隐藏”方法声明- 有关更多信息,请参见此问题


@implementation之后放在括号中的实例变量呢?他们总是私人的吗?
John Henckel

我知道它很旧...但这不是可见性修改器。这是访问修饰符。在C ++中,这是一个更重要的区别,但在Objective-C中,这也是一个区别。该变量对编译器可见。编译器只是不允许您访问它。
gnasher729 2014年

161

正如htw所说,它是可见性修改器。 @private意味着只能从同一类的实例中直接访问ivar(实例变量)。但是,这对您可能并不重要,所以让我举个例子。init为了简单起见,我们将使用类的方法作为示例。我将内联注释以指出感兴趣的项目。

@interface MyFirstClass : NSObject
{
    @public
    int publicNumber;

    @protected  // Protected is the default
    char protectedLetter;

    @private
    BOOL privateBool;
}
@end

@implementation MyFirstClass
- (id)init {
    if (self = [super init]) {
        publicNumber = 3;
        protectedLetter = 'Q';
        privateBool = NO;
    }
    return self;
}
@end

@interface MySecondClass : MyFirstClass  // Note the inheritance
{
    @private
    double secondClassCitizen;
}
@end

@implementation MySecondClass
- (id)init {
    if (self = [super init]) {
        // We can access publicNumber because it's public;
        // ANYONE can access it.
        publicNumber = 5;

        // We can access protectedLetter because it's protected
        // and it is declared by a superclass; @protected variables
        // are available to subclasses.
        protectedLetter = 'z';

        // We can't access privateBool because it's private;
        // only methods of the class that declared privateBool
        // can use it
        privateBool = NO;  // COMPILER ERROR HERE

        // We can access secondClassCitizen directly because we 
        // declared it; even though it's private, we can get it.
        secondClassCitizen = 5.2;  
    }
    return self;
}

@interface SomeOtherClass : NSObject
{
    MySecondClass *other;
}
@end

@implementation SomeOtherClass
- (id)init {
    if (self = [super init]) {
        other = [[MySecondClass alloc] init];

        // Neither MyFirstClass nor MySecondClass provided any 
        // accessor methods, so if we're going to access any ivars
        // we'll have to do it directly, like this:
        other->publicNumber = 42;

        // If we try to use direct access on any other ivars,
        // the compiler won't let us
        other->protectedLetter = 'M';     // COMPILER ERROR HERE
        other->privateBool = YES;         // COMPILER ERROR HERE
        other->secondClassCitizen = 1.2;  // COMPILER ERROR HERE
    }
    return self;
}

因此,要回答您的问题,@ private可以防止ivars被任何其他类的实例访问。请注意,MyFirstClass的两个实例可以直接访问彼此的所有ivars。假定由于程序员可以直接完全控制此类,因此他将明智地使用此功能。


20
应该提到的是,在Objective-C中使用@ public,@ proteced和@private并不常见。首选方法是始终使用访问器。
乔治·Schölly

1
@Georg,但是,除非标记可见性受限,否则如何强制使用访问器?
Greg Maletic

5
@GeorgSchölly:由于xcode 4.x +自动将@private对象的模板放入其中,因此它不再是常见的。
dawg

1
@Georg我认为@ private,@ protected可以用于涉及继承的情况,尽管还没有亲自使用它:)
chunkyguy 2011年

5
应当指出,这些天来,几乎没有理由将实例变量放在公共头文件中。它们可以直接放在@implementation块上。一旦执行此操作,无论可见性修饰符如何,它们实际上都是私有的,因为该文件之外的任何人都看不到它们。
BJ荷马2014年

14

重要的是要理解当有人说您无法访问 @private实例变量。真实的故事是,如果您尝试在源代码中访问这些变量,则编译器将给您一个错误。在早期版本的GCC和XCode中,您只会得到警告而不是错误。

无论哪种方式,在运行时,所有赌注都关闭。这些@private@protectedivars可以由任何类的对象访问。这些可见性修饰符使得很难将源代码编译成违反可见性修饰符意图的机器代码。

不要依靠ivar可见性修饰符来提高安全性!他们什么都没有提供。它们严格用于编译时执行类构建者的意愿。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.