【问题标题】:What does "@private" mean in Objective-C?Objective-C 中的“@private”是什么意思?
【发布时间】:2010-10-25 02:02:44
【问题描述】:

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

【问题讨论】:

标签: ios objective-c cocoa private


【解决方案1】:

这是一个可见性修饰符——这意味着声明为@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 中的方法总是公开的。不过,有一些“隐藏”方法声明的方法——请参阅this question 了解更多信息。

【讨论】:

  • @implementation 之后大括号中的实例变量呢?他们总是私密的吗?
  • 我知道它很旧...但它不是可见性修饰符。这是一个访问修饰符。这是 C++ 中一个更重要的区别,但它也是 Objective-C 中的一个区别。该变量对编译器可见。编译器就是不允许你访问它。
【解决方案2】:

正如 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;假设由于程序员可以直接完全控制这个类,他会明智地使用这个能力。

【讨论】:

  • 应该提到的是,在Objective-C中使用@public、@proteced和@private是不常见的。首选方法是始终使用访问器。
  • @Georg,但是除非您将 ivars 标记为受限可见性,否则您如何强制使用访问器?
  • @Georg Schölly:由于 xcode 4.x+ 会自动将@private 放入对象的模板中,因此不再那么罕见了。
  • @Georg 我认为@private,@protected 可以用于涉及继承的情况,虽然没有亲自使用过:)
  • 需要注意的是,现在很少有理由将实例变量放在公共头文件中。它们可以直接放在@implementation 块上。一旦你这样做了,无论可见性修饰符如何,它们实际上都是私有的,因为它们甚至对该文件之外的任何人都不可见。
【解决方案3】:

当有人说您无法访问@private 实例变量时,理解这意味着什么很重要。真实情况是,如果您尝试在源代码中访问这些变量,编译器会给您一个错误。在以前版本的 GCC 和 XCode 中,您只会收到警告而不是错误。

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

不要依赖 ivar 可见性修饰符来保证安全!他们根本不提供。它们严格用于在编译时执行类构建器的愿望。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-31
    • 2014-01-17
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-01
    相关资源
    最近更新 更多