2012-03-04 65 views
3

我偶然发现了这个帖子In Objective-C why should I check if self = [super init] is not nil?自我= [超级初始化]再访

我能理解this syntax

- (id)initWithString:(NSString *)aString 
{ 
    self = [super init]; 
    if (self) 
    { 
     instanceString = [aString retain]; 
    } 
    return self; 
} 

this syntax

- (id)init; 
{ 
if (!(self = [super init])) 
    return nil; 

// other stuff 
return self; 
} 

,但我还是不明白“标准”模板语法

- init { 
    if((self = [super init])) { 
     // set up instance variables and whatever else here 
    } 
    return self; 
} 

有人可以尽可能清楚地告诉(3)与(1)或(2)相比,或多或少有什么作用?我读过的所有内容都很混乱(为什么人们不能同意纯粹技术的东西看起来像政治:))

不过,当我阅读作者的文章,并且我可以模糊地理解它,远远超出了仅仅是语法糖辩论或品味的问题。例如it is said

奇怪然后,当壳体3是压倒性多见,支持1,2和4,但不兼容与壳体3已经成为standard.Curiously然后初始化,而壳体3是压倒性更常见,支持1,2和4但与情况3不兼容的初始化器已成为标准。

因此,如果可能的话,我想从Objective C Gurus得到一个深刻的哲学答案。

回答

5

来理解的关键(3)是,如果线

if((self = [super init])) { 

在C中,每个运营商有返回值,你根本不必使用它。因此,就像3 + 4返回7一样,运算符=返回刚分配的相同值。这允许你做有趣的事情是这样吧:

int a, b, c, d; 

a = b = c = d = 5; 

(这工作,因为运营商有从右到左结合这意味着a = b = 3;相当于a = (b = 3);所以b设置为三个第一,然后。 a设置为相同的值。)

所以,现在我们可以看到测试

if((self = [super init])) { 

是完全一样的

self = [super init]; 
if (self) { 

他们都做同样的事情,虽然。至于首选方案,很多人认为把表达式放入if语句是不好的做法,因为如果你不习惯它,很难注意到。苹果似乎已经与你在他们的模板中列出的第一个例子中解决,还添加了一个编译器第一次警告,如果您尝试做没有愚蠢的双括号if(())

+0

至于你关于Cocoa with Love的问题,我相信他在谈论罕见的情况,其中'[super init]'返回超类的单例实例,在这种情况下,他不想重写实例变量目的。就我而言,这更像是一种学术上的好奇心,而不是你需要担心的任何事情。 – joerick 2012-03-04 11:49:27

+0

谢谢我现在更好地理解3的语法,所以我给你正确的答案,因为这是我首先提出的问题。尽管如此,他认为[超级初始化]可以返回4个案例,而语法3只能处理3个案例,而不处理可能相当频繁的第四个案例。所以这不是品味的问题:这是一个考虑到所有例外的问题,否则你的应用程序不健壮,你不同意吗? – user310291 2012-03-04 13:21:03

+0

在Cocoa中这是一个非常罕见的情况,你想要继承这些会导致问题的对象之一。这些示例是类集群或单例对象。至少,我可以想到没有理由继承一个单身人士,而不用另外引用单身人士。至于继承类集群,通常在Cocoa中,我们更喜欢[对象组合](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html# // apple_ref/doc/uid/20000154-397934),而不是继承。 – joerick 2012-03-04 13:35:06

5

所有这三个完成完全相同的任务:调用[super init],将它分配给self(如果super的init返回不同的对象,在某些情况下可能),并测试返回的指针是否为零。如果它是零,则不做任何事情。

示例#1和#3是相同的,它们的语法稍微重新排列。 #2不同之处在于它返回一个明确的值nil,而#1和#3隐含地这样做。

哪个使用是一个味道的问题。我更喜欢#2,因为它保存了一个凹痕级别(如果可能,我喜欢避免凹痕,因为如果你深入缩进了四五级,它确实很难跟上流程)。

人们并不普遍认同哪一个使用的理由完全一样,他们不同意使用哪种缩进方式(K & R,Allman,GNU,Whitesmith,...):这是个人偏好,并没有改变逻辑。

+0

当我读到作者的文章,其意义远远超出了只是语法糖或例如据说这里的味道:)事项:“奇怪的话,同时案件3绝大多数是比较常见的,支持初始化1,2和4,但是不相容的与壳体3已经成为standard.Curiously然后,当壳体3是压倒性多见,支持1,2和4,但不兼容与壳体3已经成为标准初始化“。 – user310291 2012-03-04 11:28:34

+0

@ user310291:三个变种你引用的所有支票'nil',但是从你所引用的文章段落是关于什么的'[超级初始化]'可以退货。你所引用的三种变体在这里的表现完全相同。为了“解决”这个问题,作者提出了一个新的变体,它将'[super init]'的返回值存储在一个变量中,并将其与(仍然不变)'self'进行比较。所以对于你所引用的三种变体,它真的*是一种味道和语法问题。他们都表现完全一样。 – DarkDust 2012-03-04 12:32:13

+0

他认为[超级初始化]可以返回4个案例,而语法3只能处理3个案例,而它不能处理可能相当频繁的第四种情况。所以这不是品味的问题:这是一个考虑到所有例外的问题,否则你的应用程序不健壮,你不同意吗? – user310291 2012-03-04 13:20:21

1

如果你有一个变量并没有==,!=,>或类似的东西表达的将是真正的,如果你的变量(在这种情况下,一个指向对象)不为0,这意味着,如果你的指针唐没有指向任何东西。零和NULL为0定义的,所以你可以写

if ((self = [super init]) != nil) {} 

if ((self = [super init]) != NULL) {} 

if ((self = [super init]) != 0) {} 

或者干脆

if ((self = [super init])) {} 

了。

+1

非常感谢,非常清楚,我不能投票第二个好答案:) – user310291 2012-03-05 20:14:42

0

我也喜欢额外的“房间”使用过于冗长通过提供,很少直观......坦白地说丑陋语法我在苹果公司的代码见/城镇周围,等...

-(id) init { if (self != super.init) return nil; ... 

我可能是溺水的婴儿 - 并导致老帅哥印度人在这个过程中哭 - 但我只是坚持这一切一行 ...和记得return self; AOK为止!