Objective-C中与Java包相当的是什么?

16

Objective-C中与Java的包相对应的是什么?您如何在Objective-C中分组和组织类?


重新标记“Java”为“Cocoa”,以便Java开发人员不会因为一个实际上是Objective-C问题而感到困惑或生气。 :-) - Quinn Taylor
2
好的,但这个问题是否更多与Cocoa有关? - Arne Evertsson
2
这个问题与Cocoa无关。 - Jason Coco
1
你说得没错。虽然Objective-C与Cocoa紧密相关,但这个问题是关于语言本身而不是特定的Cocoa框架。因此我将移除Cocoa标签。 - Quinn Taylor
6个回答

32

问题1:Objective-C中与Java包相当的内容是什么?

Objective-C没有与Java包或C ++命名空间相当的内容。部分原因是Objective-C最初只是在C的非常薄的运行时层之上添加对象的,使用了最少的麻烦。不幸的是,对我们来说,当使用Objective-C时,命名冲突是我们必须处理的一件事情。你赢得了一些,你输掉了一些......

一个小的澄清(虽然这并不能让人感到安慰)是Objective-C实际上有两个扁平的命名空间 - 一个用于类,另一个用于协议(如Java的接口)。这不解决任何类名冲突,但它确实意味着您可以拥有具有相同名称的协议和类(例如<NSObject>NSObject),其中后者通常采用(“实现”)前者。此功能可以防止Java中猖獗的“Foo / FooImpl”模式,但遗憾的是它无法解决类冲突。

问题2:如何[命名]和组织Objective-C类?

命名

以下规则是主观的,但它们是命名Objective-C类的不错指南。

  1. 如果您的代码不能被其他代码运行(它不是框架、插件等,而是面向最终用户的应用程序或工具),那么您只需要避免与您所链接的代码发生冲突即可。通常,这意味着只要您使用的框架/插件/包具有适当的名称空间,就可以不加前缀。
  2. 如果您正在开发“组件化”代码(如框架、插件等),应选择一个前缀(最好是唯一的),并在某个明显的地方记录您对其使用的说明,以便他人知道避免潜在冲突。例如,CocoaDev wiki“注册表”是一个事实上的公共论坛,可用于调用前缀。但是,如果您的代码像公司内部框架一样,您可能可以使用其他人已经使用的前缀,只要您不使用该前缀的任何内容。 组织 将源文件组织好存储在磁盘上是很多Cocoa开发者不幸忽略的事情。当您在Xcode中创建新文件时,默认位置是项目目录,就在您的项目文件旁边等等。个人而言,我把应用程序源文件放在 source/,测试代码(OCUnit等)放在test/,所有资源(NIB/XIB文件、Info.plist、图像等)放在resources/等。如果您正在开发复杂项目,也可以根据功能将源代码分层存储在目录中。无论如何,良好组织的项目目录使查找所需内容更加容易。
    Xcode实际上并不关心文件位于何处。项目侧边栏的组织完全独立于磁盘位置——这是一种逻辑(而非物理)分组。您可以在侧边栏中按照自己的方式组织,而不会影响磁盘位置,这在源代码存储在版本控制中时很好。另一方面,如果您在磁盘上移动文件,修补Xcode引用是手动且繁琐的,但是可以完成。最好从一开始就创建自己的组织,并在它们所属的目录中创建文件。

    我的观点

    虽然拥有包/命名空间机制会很好,但不要指望它会发生。实际上,类冲突相当少见,而且通常在发生时非常明显。命名空间对于Objective-C来说是一个不存在的问题的解决方案。(此外,添加命名空间将消除前缀等变通方法的需要,但可能会在方法调用等方面引入更多的复杂性。)

    方法冲突导致的更加微妙和狡猾的错误,这些冲突可能是由子类还是分类(Categories)添加和/或覆盖的方法所导致的。这样做可能会导致令人讨厌的错误,因为分类的加载顺序是未定义的(非确定性的)。实现分类是Objective-C中最尖锐的边缘之一,只有当你知道自己在做什么时才应该尝试,特别是对于第三方代码,尤其是Cocoa框架类。


那么你的意思是,在Xcode中进行逻辑组织,这与磁盘位置无关,更多地为了开发者方便,是组织类的唯一方式? - raffian

4

很不幸,dotnetdevelopersjournal.com 已经消失了。 - ThomasW
谢谢提醒,我添加了一个存档链接。它看起来不太好看,但是文本都在那里。 - instanceof me

3

1

0

这样的东西怎么样(在一个目录内)?

 #define PruebaPaquete ar_com_oxenstudio_paq1_PruebaPaquete
@interface ar_com_oxenstudio_paq1_PruebaPaquete : NSObject {

并像这样导入它:

 #import "ar/com/oxenstudio/paq1/PruebaPaquete.h"
 PruebaPaquete *p = [[PruebaPaquete alloc] init];

当您遇到名称冲突时:

 #import "ar/com/oxenstudio/paq1/PruebaPaquete.h"
 #import "ar/com/oxenstudio/paq2/PruebaPaquete.h"


ar_com_oxenstudio_paq1_PruebaPaquete *p = [[ar_com_oxenstudio_paq1_PruebaPaquete alloc] init];
ar_com_oxenstudio_paq2_PruebaPaquete *p2 = [[ar_com_oxenstudio_paq2_PruebaPaquete alloc] init];

-1

嗯,我认为这里所有其他答案似乎都集中在命名冲突上,但至少错过了一个重要特性,即Java包提供的包私有访问控制

当我设计一个类时,我发现很常见的情况是我只想让一些特定的类调用它的方法,因为它们一起工作以完成任务,但我不希望所有其他无关的类调用那些方法。这就是Java包访问控制派上用场的地方,所以我可以将相关的类分组到一个包中,并使这些方法具有包私有访问控制。但在Objective-C中没有办法做到这一点。

没有包私有访问控制,我发现很难避免人们编写像这样的代码:[[[[[a m1] m2] m3] m4] m5]或[a.b.c.d m1]

更新:Xcode 4.4引入了“Objective-C类扩展头文件”,在我看来,这在某种程度上提供了“包私有访问控制”,因此如果您包括扩展头文件,则可以调用我的“包私有”方法;如果您只包括我的公共头文件,则只能调用我的公共API。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接