如何制作真正的私有实例变量?
我想创建一个无法从外部访问的实例变量。 Objective-c 中可能有类似的事情吗? 我记得苹果有私有变量之类的东西,但如果人们知道它们,他们就可以使用它们。 苹果称其为“私有 API”,但显然其他人如果发现其中的内容就可以访问该内容。
到目前为止,我相信这样的东西会创建一个私有实例变量:
@interface MyClass : NSObject {
CGFloat weight;
}
没有@property,没有@synthesize,只有上面的声明。
我还知道苹果添加了 _inFrontOfTheirPrivateInstanceVariables,但他们在某处说过,他们不喜欢看到其他人这样做,因为他们在这样做时可能会覆盖意外隐藏的实例变量。
这里有什么技巧呢?
I want to make an instance variable that can't be accessed from outside. Is something like that possible in objective-c? I remember Apple has private variables and stuff like that, but if people know about them, they can use them. Apple calls that "private API", but obviously others can access that stuff if they find out what's in there.
Until now I believed that something like this creates a private instance variable:
@interface MyClass : NSObject {
CGFloat weight;
}
No @property, no @synthesize, just the declaration above.
Also I know Apple adds a _inFrontOfTheirPrivateInstanceVariables, but they said somewhere that they don't like to see others doing that because they might override accidently hidden instance variables when doing that.
What's the trick here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
您不能不创建真正的私有实例变量。 Objective-C 是一种动态语言,因此可以访问任何变量(甚至@private)。
我的最佳方法:
在 .m 文件的实现块中使用它。 然后就是不可见并且阻塞KVC,这样KVC就不起作用了
You can not make a real private instance variable. Objective-C is a dynamic language and therefore it is possible to access any variable (even @private).
My best approach:
Use it in the implementation block of you .m file. Then it is not visible and block KVC, so that KVC will not work
您可以在
{}
内使用@private
关键字将所有后续变量声明设为私有。 默认可见性是@protected
(类似于Java中的protected
),通常效果很好。 您必须将变量明确声明为@public
才能在类外部直接访问它。此 Apple 文档 提供了有关变量范围和可见性的更多详细信息。
“私有API”和私有变量之间也有区别。 在 Objective-C 中,你不能将方法设为私有——任何人都可以调用任何方法。 有多种方法可以创建“秘密”方法,但这在某种程度上超出了这个问题的范围。 以下是一些相关的 SO 问题:
至于变量前面的前导 _,请注意 Apple 也为“私有”方法保留了此前缀。 保证避免出现问题的最佳方法是对您自己的变量和方法使用正常的命名约定。 但是,除非您从 Cocoa 继承某些东西(除了 NSObject),否则您可以相当有信心不会遇到问题。
You can use the
@private
keyword inside the{}
to make all subsequent variable declarations private. The default visibility is@protected
(which is similar toprotected
in Java) and that generally works well. You'd have to specifically declare a variable as@public
for it to be directly accessible outside the class.This Apple documentation has further details about variable scope and visibility.
There is also a difference between "private API" and private variables. In Objective-C, you cannot make methods private — anyone can call any method. There are several ways to create "secret" methods, but that's somewhat out of the scope of this question. Here are a few related SO questions:
As far as the leading _ in front of variables, be aware that Apple also reserves this prefix for "private" methods. The best way to guarantee you avoid problems is to use normal naming conventions for your own variables and methods. However, unless you subclass something from Cocoa (other than NSObject) you can be fairly confident that you won't run into problems.
使用 XCode 4 及更高版本中提供的新 LLVM 编译器,您可以在实现 (.m) 文件内的默认类别中声明
@private
变量:我发现这很方便,因为我讨厌私有变量带来的污染到我的头文件中。
With the new LLVM Compiler available in XCode 4 and later, you can declare
@private
variables in default categories inside your implementation (.m) file:I find this convenient, as I hate the pollution private variables bring into my header files.
您可以定义私有方法,只需将它们放在 @implementation 中,而不是放在 @interface 中。
类似地,您可以在 @implementation 开头的匿名块内定义私有实例变量 - 就像在 @interface 内定义公共 ivars 一样。
请参阅以下示例。
请记住,objective-C 方法是在运行时作为消息发送的(而不是 C++ 的编译时绑定),因此respondsToSelector: 仍会返回 true,而performSelector: 仍会调用该方法。 伊瓦尔将完全私有。
但是,如果您正在创建一个库,理论上没有人会知道您未在头文件中声明的任何方法。
You can define private methods by simply having them only in the @implementation, and not the @interface.
Similarly, you can define private instance variables inside an anonymous block at the start of the @implementation - as you do for public ivars inside the @interface.
See the following example.
Remember that objective-C methods are sent as messages at runtime, though (rather than C++'s compile time binding), so respondsToSelector: would still return true and performSelector: would still call the method. The ivars would be fully private.
If you were making a library, though, theoretically no one would know about any methods you didn't declare in the header files.
Objective-C 中的所有 iVar 默认情况下都受到保护。 如果您不编写访问器方法,其他类将无法看到变量。
两个例外是类别和子类。
All iVars in Objective-C are protected by default. If you don't write the accessor methods than other classes won't be able to see the variables.
The two exceptions are categories and subclasses.
用于命名实例变量的 Apple 文档没有明确警告不要像私有方法文档那样在实例变量的名称中使用下划线。
命名实例变量和数据类型
我还记得 Wil Shipley 和其他一些 OS X 开发人员之间关于下划线的对话。 由于 Obj-C 编译器的工作方式,如果 Apple 向其框架中的类添加新的实例变量,将导致所有使用这些框架的应用程序都需要重新编译。 至于预先存在的实例变量,当您踩到一个实例变量时,您应该会收到警告。
The Apple docs for naming instance variables doesn't explicit warn against using underscore in the name of instance variables like the private method documents do.
Naming Instance Variables and Data Types
I also remember a conversation between Wil Shipley and a few other OS X developers concern the underscores. Because of the way the Obj-C compiler works, if Apple were to add a new instance variable to a class in their frameworks, it would cause all apps using those frameworks to need to be recompiled. As far as pre-existing instance variables, you should get a warning when you step on one.
我在 Apple 的示例应用程序 (PaintGL) 中看到了以下用法
在 .m 文件中
免责声明:示例应用程序只有方法声明,我看到了私有属性声明 在此 SO 线程
I saw the following usage in a sample app (PaintGL) by Apple
In .m file
Disclaimer: The sample app only has method declarations, I saw the private property declaration in this SO thread