【发布时间】:2009-08-19 20:09:09
【问题描述】:
我想知道为什么 Apple 使用声明为 NSString * const 的常量(例如 kCAGravityTop)而不是常规枚举?在这种情况下,类型安全如何?据我了解,可以将任何 NSString 传递给期望此常量的方法,而不会收到任何编译器警告。
【问题讨论】:
我想知道为什么 Apple 使用声明为 NSString * const 的常量(例如 kCAGravityTop)而不是常规枚举?在这种情况下,类型安全如何?据我了解,可以将任何 NSString 传递给期望此常量的方法,而不会收到任何编译器警告。
【问题讨论】:
我不确定,但我猜这与用户将自己的扩展和子类添加到某些 Apple 产品中有关。在这种情况下,您可以重写使用的方法并捕获字符串为“MyOwnValue”的情况,然后对它做任何您想做的事情。这比修改 Apple 的枚举要容易得多,而且还可以防止你搞砸任何事情。
这也可能是为了让 Apple 更容易拥有版本独立性。对于枚举,如果您以某种方式重新排列它们的顺序,它可能会导致任何已缓存的值出现很多问题(无论出于何种原因)。如果枚举的值在保存到文件时为 1
【讨论】:
如果不在枚举类型本身中添加其他条目,则无法扩展枚举类型。因此,不可能有既被视为枚举类型的正式成员,又在正常编译过程中不可见的枚举内容。
以 CoreAnimation 为例。由于各种原因,可能存在不支持或不通过公共 API 提供的内部使用的值; “实现细节”立即浮现在脑海中。
除此之外,字符串作为常量支持扩展,正如 Eli 所暗示的那样。在调试时,它们也往往提供更多信息。 “kCAGravityTop”比“4”更具指示性。
就性能而言,使用字符串几乎没有损失。静态字符串,其中几乎每个字符串常量的每个外部声明的内部对应物实际上是由编译器处理的,并且 -isEqualToString: 方法的第一个测试是指针相等 - 非常快。不如 switch() 快,但考虑到常量隐含的代码执行幅度,switch() 和字符串比较之间的几个周期差异是无关紧要的。
【讨论】:
我怀疑原因更多是历史或风格。这就是 NeXT 框架的做法,并创造了 Cocoa“风格”。作为这种方法的一个好处,检查调试器中的值可以给出一个有意义的值(例如@“CAGravityTop”或类似的东西,而不是无意义的int)。因为静态字符串由编译器智能处理,所以比较可以通过指针比较而不是字符串相等(参见 bbum 的回答),因此这种方法对性能的影响可以忽略不计。
【讨论】:
我认为支持 NSString 的另一个原因是它可以在任何接受 id 的地方传递(例如 userInfo 或作为字典键),而原始类型(枚举)需要某种包装器
【讨论】: