【问题标题】:Question with Apple's Cocoa Documentation苹果可可文档的问题
【发布时间】:2011-01-08 23:32:02
【问题描述】:

我正在缓慢但肯定地阅读 Apple 的密集文档,但我真的要问一个问题。给出以下示例代码:

#import "MonthArray.h"

@implementation MonthArray

static MonthArray *sharedMonthArray = nil;
static NSString *months[] = { @"January", @"February", @"March",
    @"April", @"May", @"June", @"July", @"August", @"September",
    @"October", @"November", @"December" };

+ monthArray
{
    if (!sharedMonthArray) {
        sharedMonthArray = [[MonthArray alloc] init];
    }
    return sharedMonthArray;
}

- (unsigned)count
{
 return 12;
}

- objectAtIndex:(unsigned)index
{
    if (index >= [self count])
        [NSException raise:NSRangeException format:@"***%s: index
            (%d) beyond bounds (%d)", sel_getName(_cmd), index,
            [self count] - 1];
    else
        return months[index];
}

@end

这是我的问题(我很抱歉没有创建多个线程,但据我所知 - 这些都是相当基本的。)

  1. 显示 +monthArray 究竟是什么意思?我知道 + 表示它是一个类方法,但我不完全理解它有什么含义。它与普通方法究竟有何不同?

  2. 这段代码中整个 sharedMonthArray ivar 的目的是什么?我的意思是,objectAtIndex: 方法是从月份的字符串中提取的,那么有什么意义呢?

  3. [self count] 方法中的“self”是什么?我的意思是,我知道它应该是几个月,但是我在程序中哪里可以看到呢?是什么让 [self count] 计算月份而不计算 MonthArrays 的数量?

抱歉,如果我的问题是初级问题,我仍在学习 - 提前感谢您的帮助。

【问题讨论】:

  • sharedMonthArray 不是 ivar,它只是一个范围为当前文件的变量。实例变量或 ivar 是属于对象的变量。对象是类的实例,因此得名“ivar”。

标签: objective-c cocoa


【解决方案1】:

显示+monthArray 到底是什么意思?我知道 + 表示它是一个类方法,但我不完全理解它有什么含义。它与普通方法究竟有何不同?

类方法是无需提供类实例即可调用的函数。在 Objective-C 中,您通常将消息发送到实例如下:[someObject someMethod]; 使用类方法,您将消息发送到 class 本身:[SomeClass someClassMethod];。类方法通常用于执行特定于该特定类的所有对象的事情,例如创建新实例(即工厂方法)或维护/更新全局类变量。

这段代码中整个 sharedMonthArray ivar 的目的是什么?我的意思是,objectAtIndex: 方法是从月份的字符串中提取的,那么有什么意义呢?

sharedMonthArray 的目的是保存该类的单个通用实例。每次调用+monthArray 时都可以返回一个新实例,但这可能会浪费内存,因为实际上只需要一个。大多数 Cocoa 代码使用 NSArray 对象,并且不是简单的 C 样式数组,所以这个单个实例就像一个 NSArray 包装器,通过提供NSArray 实例。在内部,使用 C 样式的数组是因为无法在编译时创建静态常量 NSArray 对象。

[self count] 方法中的“self”是什么?我的意思是,我知道它应该是几个月,但是我在程序中哪里可以看到呢?是什么让 [self count] 计算月份而不计算 MonthArrays 的数量?

self 是一个自动变量,Objective-C 运行时使用它来保存接收特定消息的对象。如果你发送消息[someObject someMethod];,这将跳转到-someMethod方法,self的值将等于someObject。在此示例中,self 将是发送-objectAtIndex: 消息的MonthArray 的任何实例。根据显示的代码,对[self count] 的调用将导致方法-count 被调用,并将返回值12。

我想补充一点,这里显示的代码在 Cocoa 世界中是相当独特的。只有在创建自己的框架时,您才会真正写出这样的东西。大多数 Cocoa 源代码不会使用 C 风格的数组。这个特定示例的目的是什么?这绝对不是 Cocoa 开发者每天都会写的那种代码。

【讨论】:

  • 我在此处提供的代码可以在 Cocoa 文档的何时创建子类的示例下找到。第 103 页。
  • @Rob:这似乎是一个使用起来过于复杂的例子。至少它激发了一些讨论! :)
【解决方案2】:

这个对象被实现为一个单例,这意味着在正常使用中只会有一个实例。您会使用[MonthArray monthArray] 获得对该实例的引用,它将消息+monthArray 发送到类MonthArray。如果需要,该方法会创建 sharedMonthArray 并返回它。由于sharedMonthArray 被声明为static,它不是一个实例变量——它是一个类变量,由所有实例共享并且类方法可以访问。

-count 只是一个可以发送到MonthArray 的消息,它总是返回 12,即一年中的月数。该消息没有任何实际作用。对于未显式声明的属性,它更像是一个 getter。

[self count] 的出现是MonthArray 实例向自身发送消息的地方。在其他语言中,它可能写成this.count()

【讨论】:

    【解决方案3】:

    首先,类方法缺少返回类型——让我们解决这个问题:

    + (MonthArray *)monthArray {...}
    

    现在回答您的第一个问题:
    实例方法和类方法之间的区别在于目标,您可以调用它。顾名思义,您在类对象上调用类方法。这方面的例子是

    // call a factory-method of NSArray to create a new array:
    NSArray *array = [NSArray arrayWithObject:@"foo"];
    // obtain the current notification-center
    NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
    // obtain a singleton
    NSApplication *app = [NSApplication sharedApplication];
    

    所以恰好只有一个对象,你可以调用上面的方法——在这种情况下,检索由这个类实现的singleton

    我们来到你的第二个问题:
    当您调用[MonthArray monthArray] 时,您将返回该类的唯一要创建的实例。但是,必须有一种方法可以将该实例存储在某个地方,以便以后可以检索它。您可以在 static 变量中执行此操作(在 Java 中,这将是一个类变量)。几个月也是如此,只需要一次。
    objectAtIndex:仅用于用一个薄的 Objective-C 层包装原始 C 数组。请记住,C 很乐意让您执行 months[42] 之类的操作——只是稍后会在某个地方崩溃,因为您在那里获得的东西不太可能是 NSString。

    你的第三个问题:
    self是不是个个!它是MonthsArray 的一个实例,并且——正如这段代码显然想要的那样——唯一应该存在的实例(即存储为sharedMonthsArray 的对象)。作为MonthArray 的一个实例,它响应count 选择器并在发送此消息时简单地返回12(参见-(unsigned)count 的实现)。它不计算月份:您可以像这样更改月份

    NSString *months[] = { @"January", @"February", @"March",
    @"April", @"May", @"June", @"July", @"August", @"September",
    @"October", @"November", @"December", @"Dancing Hippo Month" };
    

    它仍然会返回 12。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多