与Java相比,Objective C中的术语和概念有哪些不同的名称?

时间:2009-08-01 22:14:10

标签: java objective-c cocoa

我希望列出一些java和Objective c之间的差异,以减轻我的困惑。当我知道所谓的事情时,它会更容易解释我的困难。

例如:

  • null - nil
  • this - self
  • 地图 - 字典(甚至不太确定这个)

我正在寻找的是与我列出的相似的比较或更正。不仅限于语言中的元素,还包括概念......

7 个答案:

答案 0 :(得分:12)

你对map = dictionary是正确的。我要补充一下:

  • @public,@ private,@ protected(默认值)仅用于变量(不是方法),并且像C ++的可见性修饰符一样工作(即,您将它们声明为节标题,而不是在每个变量之前)。
  • 类方法类似于Java中的静态方法
  • 只有两种数据结构:NSDictionary和NSArray(在不可变和可变的变体中)。这些都经过高度优化,适用于大多数情况。对于其他一切,有CHDataStructures
  • @interface不像Java的接口那样工作 - 它定义了单个类的实例变量和方法。
  • 您需要头文件。 C应该归咎于此。这非常糟糕,因为维护这些事情是一种不必要的痛苦。
  • 没有“包”的概念。最接近的是框架,但这些不应该用作Java的包(即不要仅仅为了组织你的类而创建它们)。
  • 而不是“new Class()”,而是[[Class alloc] init]。可以将“alloc”视为new运算符,将init视为构造函数。
  • id是通用对象指针,类似于Java中Object类型的引用。
  • 基类是NSObject。 NSObject的继承不是自动的,必须明确指定。

答案 1 :(得分:3)

另一个概念上的区别是在null对象上调用方法(发送消息)时的行为(为nil)。

<强>爪哇

MyClass myObject = null;
myObject.doSomething(); <-- results in a NullPointerException

<强>的OBJ-C

id myObject = nil;
[myObject doSomething]; <-- is valid

Here是关于这种行为的非常好的问题。

答案 2 :(得分:3)

关于alloc / init的哲学答案。

init不是构造函数。从概念上讲,Objective-C中不存在“构造”。在Java(以及带有构造函数的其他语言)中,调用构造函数将返回准备好的对象的新实例化。 在Objective-C 中没有完全相同的内容。 (有人可能会说,+ array,+ arrayWithObjects等便利类方法在技术上是构造函数,因为它们包含了分配和初始化,但我认为它们仍然不是与Java构造函数相同的构造函数。)

我们所拥有的是分配和初始化的概念,两个不同的步骤,当它们一起执行时,就像它们是“构造函数”一样。类方法+ alloc只是从系统中请求一个适当大小的内存块。 IIRC,它使用calloc()函数来执行此操作。无法保证在执行alloc函数期间将发生任何归零。这意味着我们需要自己进行初始化,我们通过立即调用-init方法来进行初始化。

然而,-init(和所有衍生物)只不过是普通的实例方法。您可以随时发送消息,以便将对象实例“重置”为其原始初始化状态(尽管必须考虑这样做的一些内存管理后果)。这也意味着你可以做这样荒谬的事情:

NSUInteger count = [[[NSArray alloc] autorelease] count];

我想不出你想要这样做的一个很好的理由,但关键是你可以。它进一步强调 init不是构造函数。在上面的示例中,对象在+ alloc方法返回时存在。但是,它可能未正确初始化,这意味着无符号整数“count”可能不为零。它可能是,但依靠这种行为是不正确的(当然,除非另有说明)。

将构造分解为分配和初始化的一个优点是我们可以对已经初始化的内容进行很大程度的控制。例如,在Java中,每个方法签名只能有一个构造函数。换句话说,如果你有一个构造函数接受一个“Object”参数,那么这是唯一可以构造的构造函数。您不能创建另一个也采用单个Object参数的构造函数。

在Objective-C中,参数类型不是方法签名的一部分(称为“选择器”),因此我可以像这样创建一个初始化器:

- (id) initWithAnObject:(id)anObject;

但是,我也可以创建另一个初始化程序:

- (id) initWithADifferentObject:(id)anObject;

我可以将它们设置为对它们被调用的对象进行完全不同的初始化。这是令人难以置信的有用的!

将构造拆分为分配和初始化的另一个非常有用的方面是您可以链接初始化程序。 AFAIK,你不能用像Java这样的语言在构造函数中调用构造函数(好吧,你可以,但它没有相同的效果)。但是,在Objective-C中,您可以执行以下操作:

- (id) initWithCapacity:(NSUInteger)initialCapacity {
  if (self = [super init]) {
    [self setInitialCapacity:initialCapacity];
  }
  return self;
}

- (id) init {
  return [self initWithCapacity:0];
}

现在当你分配/初始化这样设置的对象时,即使你调用了init,它也会“重定向”并使用initWithCapacity初始化器。 (这是NSArray的init方法的工作原理)这意味着您可以使用条件初始值设定项。例如,让-init方法在某些条件下调度到一个初始值设定项,但在不同条件下使用不同的方法。

总之,“分配和初始化”的Objective-C模型比构造理念强大得多。作为程序员,您可以更好地控制对象的初始设置阶段。这是一个非常自由的转变。

ps - init不是构造函数!;)

答案 3 :(得分:2)

接口=协议

Field =实例变量(“ivar”)

ArrayList = Array

调用方法=发送消息

您列出的是正确的。

答案 4 :(得分:2)

脱离我的头顶:

  • 序列化=存档
  • 实例变量通常通过属性而不是显式的get / set访问器来访问。 (在过去,我们过去常常编写访问器,但即便如此,它们的格式通常为foo / setFoo,而不是getFoo / setFoo。)
  • 动作/按钮/鼠标/事件监听器大致相当于IBAction,尽管在Cocoa中设计GUI的方式与Java完全不同。
  • 类定义由class(对于实例变量和方法声明)和@interface(对于实际方法代码)指令定义,而不仅仅是一个@implementation块。

答案 5 :(得分:2)

以前的答案涵盖了大多数“短语”差异,但有几个关键的概念差异值得一提......(请注意,我只提到纯粹的Objective-C问题,而不是Cocoa。)

  • 类有一个平面命名空间,协议有一个。没有包或包层次结构这样的东西。在应用程序中,所有类名必须是不同的(并且所有协议名称必须是不同的)。这通常通过使用~2个字母的前缀来实现。
  • 异常保留用于异常流程,几乎总是由于程序员错误。如果需要,返回NSError可以更好地为95%以上的Java例外提供服务。
  • 考虑使用类别而不是一次性子类,但两者都应该谨慎而谨慎地进行。 (类别使继承层次结构受到较少的约束,但会影响类的所有实例。当您通常进行子类化时,它们通常是一个可靠的选择,例如UI元素。)经常(在两个目标中) C和Java)最佳解决方案是使用合成。
  • 您可以根据需要使用动态类型,只需要知道它是一把双刃剑。它消除了对大量转换的需要,但是在Java中编译时捕获的错误将被推送到Objective-C中的运行时。静态类型可以根据需要在任何地方使用,并提供更高的编译时安全性。 (Java开发人员经常将非静态类型视为语言缺陷,但最好能够理解它所带来的灵活性。)
  • 您可以自由地混合C功能和库,无需 JNI包装器。但是你也得到了直接C的所有琐事和限制。是的,如果我们能够消除对头文件的需求,那将是非常好的,但对于基于C语言来说,这不会发生。生活并不总是公平的。 : - )

答案 6 :(得分:0)

对于实现FastEnumeration协议(java中的接口)的类,通常使用迭代器进行简单枚举,而不是使用迭代器进行简单的枚举

for(容器中的Class *元素)

http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocFastEnumeration.html