首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >目标C-这是不是一个实施工厂的坏地方?

目标C-这是不是一个实施工厂的坏地方?
EN

Stack Overflow用户
提问于 2013-06-09 13:02:37
回答 3查看 849关注 0票数 3

我实现了旧的init作为工厂模式,但在一个特定的情况下(而不是其他!)我收到分析器关于内存泄漏的警告。事实上,看看可可内存管理政策规则,可以返回+1保留计数对象的是alloc,而不是init

因此,看来:

  1. 严格地说,释放self并从init返回一个新对象是违反规则的。
  2. 互联网上的许多地方都在推广这种技术,而且由于alloc/init的串联特性,这种方法确实有效。
  3. 分析者有时抱怨这一点,有时却不抱怨。

所以..。我们一直都在做错事吗?

EN

回答 3

Stack Overflow用户

发布于 2013-06-09 23:05:24

您可以这样实现init,它应该释放self以平衡alloc调用中的保留计数。

代码语言:javascript
运行
复制
- (id)initWithSomething:(id)something
{
    [self release]; // don't need this line for ARC
    self = nil;
    return [[PrivateSubClass alloc] initWithSomething:something];
}

如果经常将init作为工厂方法来实现的话。例如NSArrayNSDictionaryNSString

票数 2
EN

Stack Overflow用户

发布于 2013-06-09 14:02:03

正如gaige所说,如果你发布一段代码而不是解释,它会更加清晰。

无论如何,您可以将您的工厂移到类方法中,这样您就不会有这样的问题了。我的意思是这样的:

代码语言:javascript
运行
复制
MyClass* instance = [MyClass instanceWithParameters:params];

@interface MyClass
+ (MyClass*) instanceWithParameters:(ParamType)params;
@end
票数 0
EN

Stack Overflow用户

发布于 2013-06-10 00:28:27

在不知道导致分析器行为的代码是什么的情况下,很难判断,但作为一般规则,这里有几种定义init/工厂方法的编译器友好的方法。

经典alloc/init

代码语言:javascript
运行
复制
- (instancetype)initWithParameter:(id)parameter {
    if(self = [super init]) {
       _parameter = parameter; 
    }
    return self;
}

用法

代码语言:javascript
运行
复制
MyCustomClass * myInstance = [[MyCustomClass alloc] initWithParameter:foo];

这将产生一个具有+1保留计数的实例。在ARC下,这将被自动正确地管理,因为它遵循NARC规则(New,Alloc,rule,Copy)。出于同样的原因,在预ARC环境中,客户端必须显式地发布它.

自定义工厂法

圆弧

代码语言:javascript
运行
复制
+ (instancetype)canIHazInstanceWithParameter:(id)parameter {
    return [[self alloc] initWithParameter:parameter]; // assuming -initWithParameter: defined
}

预弧

代码语言:javascript
运行
复制
+ (instancetype)canIHazInstanceWithParameter:(id)parameter {
    return [[[self alloc] initWithParameter:parameter] autorelease]; // assuming -initWithParameter: defined
}

用法

代码语言:javascript
运行
复制
MyCustomClass * myInstance = [MyCustomClass canIHazInstanceWithParameter:foo];

在ARC和预ARC中,该方法都返回一个自动释放的实例(在预ARC实现中这显然更明确),它不需要由客户端管理。

备注

  • 您可能注意到了instancetype关键字。这是Clang引入的一个方便的语言延伸,在实现您自己的构造函数/工厂方法时,它将编译器变成一个好朋友。我写了关于这个问题的文章,这可能和你有关。
  • 工厂方法是否优于init方法是值得商榷的。从客户端的角度来看,它在ARC下没有多大区别,前提是您要小心遵循命名约定,即使我个人倾向于在接口中公开工厂方法,而只在内部实现自定义init方法(正如我在上面的示例中所做的那样)。与其说这是一个实际的问题,不如说是一个风格的问题。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17009872

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档