【问题标题】:Class methods which create new instances创建新实例的类方法
【发布时间】:2011-08-24 16:24:10
【问题描述】:

除了标准的[[MyClass alloc] init] 模式之外,一些对象是从MyClass *obj = [MyClass classWithString:@"blabla"] 等静态方法构建的

根据广泛使用的内存管理指南(包括 Apple 的),您只需负责释放您 alloc 的对象。

谁能为我提供此类方法的模板?你如何返回分配的对象([self alloc]; return self;,也许)?你如何确保它会被发布?

【问题讨论】:

  • 不仅是 +alloc — 任何名称以 allocnewcopymutableCopy 以及 -retain 开头的方法。

标签: objective-c memory-management class-method initializer


【解决方案1】:

它们是类方法,而不是静态方法1。这种创建自动释放对象的特定类型可以称为“工厂方法”(以前也称为“便利构造函数”),它们在the Concepts in ObjC Guide 中进行了讨论。他们是这样的:

+ (instancetype)whatsisWithThingummy: (Thingummy *)theThingummy {
    return [[self alloc] initWithThingummy:theThingummy];
}

Whatsis 是您的班级,Thingummy 是您班级使用的另一个班级。

如果您不使用 ARC 进行编译,则惯例是在返回实例之前autorelease

instancetype keyword 是 Clang 针对这些方法引入的;结合self(这是类方法中的class object本身2),它允许正确的子类行为:该方法生成接收消息的类的实例。3instancetype 允许编译器进行比id 更严格的类型检查。

框架的子类中的这种用法说明:+[NSString stringWithFormat:] 返回一个 NSString 实例,而 +[NSMutableString stringWithFormat:] 返回子类 NSMutableString 的一个实例,不需要 NSMutableString 显式覆盖该方法.

正如 [Fundamentals][1] 文档所讨论的,这些工厂方法还有其他用途,例如访问单例,或在执行之前评估必要的内存分配(可能,但不太方便,使用标准的alloc/init 对)。


1Java 或 C++ 中的“静态方法”,Objective-C 中的 "class methods"There's no such thing as static methods in ObjC

2而在实例方法中,self 显然是对实例的引用。

3以前,like the usual initialization methods (initWith...),您会使用 id 作为返回类型。使用特定的类名会不必要地强制子类覆盖该方法。

【讨论】:

  • +1 表示id 作为返回类型,+1 表示文档引用,+1 表示类方法,+1 表示便利构造函数。
  • @Bavarious:谢谢。我很高兴你没有为糟糕的元句法变量拿走一点。 :)
  • +1 用于脚注提及 Clang 的 instancetype 扩展。
  • +1,尽管我不得不克制自己不要编辑你的元句法变量。
  • @Josh:'以前,像通常的初始化方法 (initWith...),你会使用 id 作为返回类型'。当没有作为类方法的一部分合并时,id 是否仍用作带有样式 -initWith 的实例方法的返回类型?
【解决方案2】:

从工厂方法返回的对象应该是自动释放的,这意味着当关联的自动释放池耗尽时它们将被清理。这意味着您不拥有返回的对象,除非您 copyretain 他们。以下是工厂方法的示例:

+ (id)myClassWithString:(NSString *)string {
    return [[[MyClass alloc] initWithString:string] autorelease];
}

【讨论】:

【解决方案3】:

这些方法只是返回对象的自动发布版本。

+(MyClass*)class
{
  MyClass* object = [[MyClass alloc] init];
  return [object autorelease];
}

【讨论】:

  • 因为继承,工厂方法通常有id作为返回类型。
【解决方案4】:

使用 ARC 和最新编译器的现代方法是:

+ (instancetype) myClassWithString:(NSString *)string {
     return [[MyClass alloc] initWithString:string];
}
  • 无需使用 ARC 自动释放。
  • instancetype 提供更好的编译时间检查,同时使子类化成为可能。

【讨论】:

  • 将方法重命名为以“new”开头还是使用 NS_RETURNS_RETAINED 属性宏不是更好吗?据我了解,这样做会告诉 ARC 它收到一个 +1 对象,调用者应承担该对象的所有权。但这不是必需的,因为默认的自动发布实现将达到相同的结果。
猜你喜欢
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-23
  • 2011-11-12
  • 1970-01-01
相关资源
最近更新 更多