【问题标题】:Private variables in Objective-C [closed]Objective-C中的私有变量[关闭]
【发布时间】:2014-08-31 18:30:37
【问题描述】:

可可开发教程声明所有实例变量在声明时都是私有的

访问器

默认情况下,Objective-C 中的所有实例变量都是私有的,所以你 在大多数情况下,应该使用访问器来获取和设置值。有 两种语法。这是传统的 1.x 语法:

[photo setCaption:@"Day at the Beach"];
output = [photo caption];

第二行的代码没有读取实例变量 直接地。它实际上是在调用一个名为 caption 的方法。大多数情况下, 您不会在 Objective-C 中的 getter 中添加“get”前缀。

每次你想要价值时都不需要访问器不是更容易吗?为什么它们会自动声明为私有?

【问题讨论】:

  • 默认情况下它们是私有的。这在我所知道的所有编程语言中都很常见,例如默认情况下要保护或私有的变量。
  • 例如,C++ 有 structclass,它们在所有意图和目的上都是相同的概念,除了 struct 成员默认是公共的,class 成员是私有的. Java 和 Objective-C 没有 struct 等效项。
  • @TheParamagneticCroissant - Objective-C 的类方案不包括结构。例如,您不能将结构放在 NSArray 中。
  • @TheParamagneticCroissant 你做到了。 HotLicks 指出Java 和Objective-C 没有struct 等效项(与您在C++ 中找到的相同)。你不同意他,但你的不同意是错误的。使用 Objective-C struct 无法做到使用 C++ struct 可以做到的事情。
  • 我在寻找更多的理由,但我认为有这么多意见的事实是因为没有一个很好的明确理由。

标签: objective-c instance-variables getter-setter accessor


【解决方案1】:

每次你想要值时都不需要访问器不是更容易吗?

也许它会“更容易”,但在大多数情况下,它就是不正确的。

Setter 是一个更好的例子,但也需要使用返回对象的 getter。这种 getter 的典型(自动生成)实现等价于

- (Foo *)foo {
    return [[_foo retain] autorelease];
}

这不是巧合——如果你只是直接用对象的实例变量四处寻找,那么一旦包含对象被释放,它的实例变量也会被释放,所以使用 a 是错误的对象释放后的属性。

使用 setter,问题列表会更长。同样,还有所有权问题:典型的 setter 会做类似的事情

- (void)setFoo:(Foo *)newFoo {
    [newFoo retain];
    [_foo release];
    _foo = newFoo;
}

同样,如果您直接使用 ivar,您要么只是泄漏内存,要么需要手动、明确地跟踪所有权,这违反了 DRY(并且极易出错)。

然后,键值观察也不起作用。如果您只是更改对象内部的指针,注册的观察者将不会被告知这一点。当属性发生变化时,setter(以及其他)负责发送适当的键值观察者消息。

【讨论】:

  • 这个答案与任何使用 ARC 的人都不太相关......这可能是大多数 Objective-C 开发人员,对吧?
  • @nhgrif 为什么它与使用 ARC 的人无关?
  • 因为 ARC 不允许您使用 retainreleaseautorelease?即使您直接访问实例变量,也不需要任何带有 ARC 的内存管理代码...
  • @nhgrif 是的,但是答案中的代码不是 人们会编写的实际代码,而是演示了自动生成的 setter 和 getter 如何工作的东西。这些方法即使在 ARC 下也做同样的事情,但可能你不会在任何地方找到像这样的实现,因为编译器直接生成等效的 LLVM IR 和/或汇编代码......此外,实现的公开和键值观察即使您完全无视内存管理,它仍然是绝对相关的。
  • 我想说的是,当我们直接使用 ARC 访问实例变量时,retainreleaseautoretain 仍然不是问题。您警告说我们可能会导致内存泄漏......但直接接触变量并不比通过访问器更有可能......
【解决方案2】:

不,这并不容易,实际上语法是相似的。

self->_caption;
_caption; // here self-> is implicit.

对比

[self caption];
self.caption;

我认为直接访问 ivars 比访问器更容易的说法并不准确。


访问器的原因是抽象。它可能是访问器的子类并替换访问器的功能。可以重构内部结构,但保留与访问器相同的接口。访问器比直接访问 ivars 更灵活,功能更强大。

【讨论】:

  • 这忽略了私有实例变量需要开发者编写setter/getter这一事实。语法可能不会让它变得更容易......但是私有变量意味着您需要实现更多方法。
  • @nhgrif 我更新了我的答案以使我的观点更清楚。
  • 我删除了反对票。不过,“不,这并不容易”仍然困扰着我。也许“不,这并不容易,因为我们可以使用 @property 并获得公共变量的易用性以及私有实例变量的抽象”?
猜你喜欢
  • 2010-10-17
  • 2013-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多