【问题标题】:Objective-C: how to prevent abstraction leaksObjective-C:如何防止抽象泄漏
【发布时间】:2010-03-30 00:55:53
【问题描述】:

我发现在 Objective-C 中我必须将实例变量声明为我的类接口的一部分,即使这些变量是实现细节并且具有私有访问权限。

在“主观”C 中,我可以在我的 .c 文件中声明一个变量,并且它在该编译单元之外是不可见的。我可以在相应的 .h 文件中声明它,然后在该编译单元中链接的任何人都可以看到该变量。

我想知道在 Objective-C 中是否有等效的选择,或者我是否确实必须为我的类声明 .h 中的每个 ivar。

阿里。

【问题讨论】:

  • +1,用于主观 C 注释。

标签: objective-c language-features abstraction


【解决方案1】:

阿里,

关于如何完成“不可见”实例变量声明的一个很好的参考可以be found here 尊敬地归功于 Matt Gallagher。

希望对你有帮助, 弗兰克

【讨论】:

  • 对。真正回答我的问题的一点是,我可以将@interface 的一部分放在我的 .m 文件中。谢谢你的指点。
【解决方案2】:

传统上需要实例变量来确定类的大小。直接访问 ivars 一直是不好的做法,这不是重点。在现代运行时,这不太必要,但无论如何,除非客户端依赖于类的 ivars,否则这不是抽象泄漏,这应该是不可能的,因为您将它们声明为 @protected@private,对吧?

【讨论】:

  • 感谢您指出显式枚举ivars的初衷。我一直在使用真正的动态语言(Python、Lisp),我忘记了有些语言想在编译时知道大小。在许多方面,学习 Objective-C 就像是一次记忆之旅。或者在矿井下:我可以看到在语言的整个生命周期中积累的所有不同的沉积层。
  • @iter:在 Objective-C 中甚至不再需要。现代运行时的工作方式与 Python 非常相似,实例变量可以随意分配而无需在标头中声明,但该语言仍然沿用其过去的语法。
  • 我想我可能在前几天遇到了这个问题,但是当我开始遇到间歇性的 objc_msgSend_fixup 错误时。我不是 100% 确定,但是当我删除 object_setClass 时问题就消失了,我用来将对象转换为具有附加属性的自定义类。
  • @Elise van Looij:那是因为object_setClass 不是演员,而且这根本不是正确的做法。
  • 请注意,我特别说您可以在对象上分配任意变量,而不是您可以安全地将一个类的对象变成其他任意类的对象。那是行不通的部分。
【解决方案3】:

要限制访问,您可以使用@private@protected 关键字:

@interface Foo : NSObject {
    @private
    int barPrivate;

    @protected
    int barProtected;

    @public
    int barPublic;
}
@end

编辑: 从头开始,结果我真的需要睡觉了。

【讨论】:

  • 对了,不能用类别添加实例变量。
  • 使用不同的 bar 值创建多个实例,您会看到 — bar 是一个全局变量。
  • @Chuck:查看我的上一次编辑。凌晨 4 点 33 分,CBG 签字。自我提醒:醒来后复习你在过去 2 小时内编写的所有代码。
【解决方案4】:

ivars 默认为@protected(尽管@private@protected 不保证其他类无法访问它们——您始终可以使用getValue:forKey: 访问ivars)。在任何情况下,您都不应该直接从其他类直接访问 ivars ——“选择”是是否将 ivars 公开为属性(您只需要依赖所有遵循约定的类来不直接访问 ivars)。

在新的objective-c运行时,你根本不必声明ivars,因为它们可以在运行时合成,但不幸的是,这不适用于iPhone模拟器,所以现在,最好只是在 .h 文件中声明所有 ivars。

【讨论】:

  • 我不太担心阻止客户端代码对我的代码做一些奇怪的事情,而更多地担心告诉客户端程序员更多关于我的实现的信息,而不是他想知道的。当我阅读 .h 文件时,我想了解我正在使用的库的“外部”形状。如果我想知道它的内部工作原理,我会视情况阅读 .c 或 .m 。我喜欢将这两个分开。
  • 我同意 - ivars 在 .h 文件中很烦人,但如上所述,我认为这是为了编译器的利益。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-15
  • 2020-10-20
  • 2011-09-30
  • 2010-12-20
相关资源
最近更新 更多