我对在Objective-C编写的init方法的普遍问题。
我看到它无处不在(苹果公司的代码,书籍,开放的源代码等)的init方法应该检查一下自我= [超级初始化]不与初始化,然后再继续为零。
对于一个init方法的默认模板,苹果是:
- (id) init
{
self = [super init];
if (self != nil)
{
// your code here
}
return self;
}
为什么?
我的意思是init曾经打算返回nil什么时候? 如果我呼吁NSObject的init和得到无回,则必须有所真的搞砸了吧? 而在这种情况下,你可能也不会写一个程序...
难道真的是常见的一类的init方法可能返回零? 如果是这样,在什么情况下,为什么?
例如:
[[NSData alloc] initWithContentsOfFile:@"this/path/doesn't/exist/"];
[[NSImage alloc] initWithContentsOfFile:@"unsupportedFormat.sjt"];
[NSImage imageNamed:@"AnImageThatIsntInTheImageCache"];
... 等等。 (注:如果文件不存在的NSData可能会抛出异常)。 有相当多的地区,回访为零时出现了问题,因为这是标准的做法,以检查零几乎所有的时间,一致性的缘故预期的行为。
这种特殊的成语是标准,因为它适用于所有情况。
虽然少见,会有情况下...
[super init];
...返回不同的实例,因此要求分配给自己。
而且会有情况下,它会返回nil,因此要求零检查,以便您的代码不会尝试初始化实例变量插槽不再存在。
底线是,它是使用记录正确的模式,如果你不使用它,你就错了。
我认为,在大多数类,如果从[超级的init]的返回值是零,你选择了它的建议,标准的做法,然后返回过早,如果零,基本上你的应用程序仍然不会正常工作。 如果你想想看,即使是,如果(自我!=无)检查是存在的,为你的类的正常运行,你其实也需要自我为非零99.99%的时间。 现在,假设,无论出于何种原因,[超级初始化] 做回零,基本上你对零支票基本上把责任推到你的类,调用者在那里它可能会失败,反正,因为它自然会假定电话是成功的。
基本上,我得到的是,时间99.99%,如果在(自我!=无)不买任何东西更稳健性方面,因为你只是把责任推到你的调用。 要真正能够稳健地处理这个问题,你实际上需要把支票在您的整个调用层次。 即使如此,它会买你的唯一的事情是,你的应用程序将失败多一点清洁/强劲。 但它仍然会失败。
如果库班擅自决定以零回报为[超级初始化]的结果是,你几乎滚泥编不管怎么说,这是更多的指示,库类的作家提出的实施是一个错误。
我觉得这是比较旧式的编码建议,当应用程序在跑了很有限的内存。
但对C级代码,我仍然会通常检查的malloc()对NULL指针的返回值。 然而,对于Objective-C的,直到我找到相反的证据,我想我通常会跳过如果(自我!=无)检查。 为什么不一致?
因为,在C和malloc的水平,在某些情况下,你实际上可以部分恢复。 而我认为,在Objective-C,在例99.99%,如果[超级初始化]确实返回零,你基本上滚泥版,即使您尝试来处理它。 你还不如干脆让应用程序崩溃,并处理善后事宜。
这是一种上述意见的摘要。
比方说,超收益nil
。 什么会发生?
如果你不遵守的规则
你的代码是在你中间会崩溃init
方法。 (除非init
什么都不做的意义)
如果按照惯例,不知道超可能会返回零(大多数人在这里结束)
您的代码是probalby在某一点后会崩溃,因为你的情况是nil
,在那里你预期不同的东西。 或者,你的程序会出人意料地表现得没有崩溃。 噢亲爱的! 你想要这个吗? 我不知道...
如果按照惯例,心甘情愿地让你的子类返回nil
您的代码文件应明确规定(!):“回报......或无”,和你的代码的其余部分需要被处理为此做好了准备。 现在,它是有道理的。
通常情况下,如果你的类直接派生自NSObject
,你不会需要。 然而,这是一个很好的习惯进入,因为如果你的类从其他类派生,其初始化可能会返回nil
,如果是这样,你可以初始化,然后捕获和正常运行。
是的,备案,我按照最佳做法,并把它写在我的班,即使是那些直接从派生NSObject
。
你说的没错,你可以经常只写[super init]
,但不会对一切事情的一个子类的工作。 人们更愿意只记住一个标准的代码行,并用它所有的时间,即使它只是有时必要的,因此,我们得到的标准if (self = [super init])
这需要的零返回两者的可能性,比其他对象的可能性, self
返回考虑。
一个常见的错误是写
self = [[super alloc] init];
返回超类,这是不是你在子类的构造函数/初始化想要的东西的一个实例。 你回来的对象不以子类的方法,这可能会造成混淆响应,并生成有关不reponding的方法或标识符没有找到,等混乱的错误
self = [super init];
需要如果超类有成员(变量或其他对象)来建立子类成员之前先初始化。 否则,objc运行时他们都初始化为0或零 。 ( 不像ANSI C,这往往分配的内存块而不清除它们在所有 )
是的,基类初始化失败可能是因为内存不足,错误,缺失的部分,资源获取故障等的所以零检查是明智的,只需不到几毫秒。
这是为了检查intialazation工作,如果语句如果init方法没回零,所以它的一个方法来检查创建的对象工作正常返回true。 几个原因,我可以认为初始化的可能也许会失败的一个被覆盖的init方法的超类不知道的或类似的东西,我不会认为这是常见的,但。 但是,如果它确实发生,它能够更好没事发生碰撞我supose所以它总是检查...
在OS X,它不是可能的-[NSObject init]
失败由于内存的原因。 同样不能说的iOS。
此外,子类可能返回一个类时的书写好的做法nil
因任何原因。