RE: Looking at self = [super init].
RE: Looking at self = [super init].
- Subject: RE: Looking at self = [super init].
- From: Lee Ann Rucker <email@hidden>
- Date: Mon, 01 Jun 2015 07:30:21 +0000
- Thread-topic: Looking at self = [super init].
> The "==" case that has been mentioned just omits the second step because self isn't modified by calling [super init]. And the equivalent statements for the other case (! / ==) do the same thing except that the test step is the inverse.
init is allowed to return a different "self", so if you skip the assignment you're looking at a stale self.
________________________________________
From: cocoa-dev-bounces+lrucker=email@hidden [cocoa-dev-bounces+lrucker=email@hidden] on behalf of Steve Christensen [email@hidden]
Sent: Sunday, May 31, 2015 6:45 PM
To: Alex Zavatone
Cc: Cocoa-Dev List
Subject: Re: Looking at self = [super init].
No, it doesn't make a difference. In both cases the compiler will generate a "test and branch" to the method's epilogue. For the "=" case:
if (self = [super init]) ...
is equivalent to:
if ((self = [super init]) != nil) ...
is equivalent to:
self = [super init];
if (self) ...
is equivalent to:
self = [super init];
if (self != nil) …
They all:
• Call the superclass' -init method.
• Store the result in self.
• Test if self is not equal to nil/zero.
• Branch to method epilogue (or at least past {...}) if not.
The "==" case that has been mentioned just omits the second step because self isn't modified by calling [super init]. And the equivalent statements for the other case (! / ==) do the same thing except that the test step is the inverse.
In my opinion having a macro to replace the "self = [super init]" idiom saves you a couple of seconds of typing — once; it obfuscates behavior since you need to locate the macro to see what it does if you forget; and it is applicable only to subclasses where you're calling a superclass' -init method. It doesn't help for, e.g., -initWithCoder:, -initWithFrame:, etc., which then means you need to come up with a bunch of other macros to handle those cases or you're special-casing [super init].
Choosing to do an early return or not is up to you. Personally I prefer the "if (self != nil) {...}" case, even if the method is long so that I can see structure. To say more risks getting into a "religious" discussion that nobody wins. :)
> On May 30, 2015, at 3:20 PM, Alex Zavatone <email@hidden> wrote:
>
> Actually, i was typing by habit and included == instead of = by mistake.
>
> So, while you answered the question, you may have answered the wrong question.
>
> The question is not for
>
> if ( self == [super init])
>
> It's
>
> if ( self = [super init])
>
> How does that change your answer?
>
> On May 30, 2015, at 6:08 PM, Michael David Crawford wrote:
>
>> While in principle machine code implementations of subroutines can
>> return from several different places, in practice they don't. Rather
>> the compiler's code generator emits a branch instruction to the end of
>> the subroutine, there there is an "epilog".
>>
>> There are many good reasons for returning from the middle in certain
>> specific cases; what if the only epilog you need is an "rts"?
>> Branching to the epilog could cause a cache miss.
>>
>> I expect the compiler developers know all about this but don't
>> typically avail themselves of it because writing compilers is
>> difficult.
>>
>> To be clear, the following source code:
>>
>> - (id) init
>> {
>> if ( self == [super init] ) return nil;
>>
>> // lots of code goes here
>>
>> return self;
>> }
>>
>> ... is implemented as something like this, but in machine code:
>>
>> - (id) init
>> {
>> id result;
>> if ( self == [super init] ){
>> result = nil;
>> goto epilog;
>> }
>>
>> // lots of code goes here
>> result = self;
>>
>> epilog:
>> return result;
>> }
>> Michael David Crawford, Consulting Software Engineer
>> email@hidden
>> https://urldefense.proofpoint.com/v2/url?u=http-3A__www.warplife.com_mdc_&d=BQIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=ie7S-J__EKnfyVOBV7-jV2rZ--p47O6vkyTklpDM3h4&m=Z8vcdjmsMKlbvM2wCAfNohcqAEcoUBSmr2LdV39oZp8&s=0LcsucVzgw_rFosbryao4sTH3L4wj7OecTlM6LeQ3gU&e=
>>
>> Available for Software Development in the Portland, Oregon Metropolitan
>> Area.
>>
>>
>> On Fri, May 29, 2015 at 6:25 PM, Graham Cox <email@hidden> wrote:
>>>
>>>> On 30 May 2015, at 3:22 am, Alex Zavatone <email@hidden> wrote:
>>>>
>>>> // We don't care if this gets long.
>>>
>>>
>>> My take is that you're rewriting a well-recognised idiom to solve a non-existent problem.
>>>
>>> The well-recognised idiom makes it easy to verify it's correct. Hiding a different construct inside a macro obscures that, making it harder to verify the code. It's not "wrong" exactly, just harder to see at a glance that it's right.
>>>
>>> The non-existent problem you're trying to solve is that the gap between a pair of braces could get large. So what? Early returns can be another source of bugs, so structural purists would tell you that you shouldn't do that. Sometimes I think it's justified, but not usually worthwhile. Another religious issue is whether matching braces should line up or not. Personally I prefer that they do, at the cost of an extra line. Because you aren't doing that, your long distance between braces is bothering you, because you're losing track of where it started (I assume that's why it's bothering you). If you line up the braces that is much less of an issue.
>>>
>>> Source code is for humans, so it should be as readable as you can possibly make it. Macros often hinder that. Unaligned braces hinder that. Multiple statements per line hinder that.
>>>
>>> Factoring code helps, so I'd suggest that's the better way to solve this. (and it's also beneficial when it comes to making sure that -initWithCoder: and other initializers that don't correctly follow the designated initializer rule can get access to your common initialization. While this is rarely a problem, I did notice that the recent change to encourage the use of -initWithCoder: for unpacking NSViews from a nib breaks this long-standing rule and so a common init method that both can call is a simple workaround).
>>>
>>> --Graham
>>>
>>>
>>>
>>> _______________________________________________
>>>
>>> Cocoa-dev mailing list (email@hidden)
>>>
>>> Please do not post admin requests or moderator comments to the list.
>>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>>
>>> Help/Unsubscribe/Update your Subscription:
>>>
>>> This email sent to email@hidden
>>
>> _______________________________________________
>>
>> Cocoa-dev mailing list (email@hidden)
>>
>> Please do not post admin requests or moderator comments to the list.
>> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>>
>> Help/Unsubscribe/Update your Subscription:
>>
>> This email sent to email@hidden
>
>
> _______________________________________________
>
> Cocoa-dev mailing list (email@hidden)
>
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
>
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden