Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.objective-c > #215 > unrolled thread
| Started by | Jon Rossen <jonr17@comcast.net> |
|---|---|
| First post | 2015-11-22 13:39 -0800 |
| Last post | 2015-11-24 18:29 -0800 |
| Articles | 12 on this page of 32 — 5 participants |
Back to article view | Back to comp.lang.objective-c
A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-22 13:39 -0800
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-22 14:48 -0800
Re: A question on designated initializers Louis Wu <louiswu@ringworld.net> - 2015-11-22 16:26 -0800
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-22 17:24 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-23 02:39 +0100
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-23 01:18 +0100
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-22 16:49 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-23 02:02 +0100
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-27 17:19 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-28 13:22 +0100
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-28 17:37 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-29 03:45 +0100
Re: A question on designated initializers Don Bruder <dakidd@sonic.net> - 2015-11-22 19:15 -0800
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-23 18:44 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-24 04:58 +0100
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-24 16:42 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-25 02:00 +0100
Re: A question on designated initializers Greg Parker <gparker@apple.com> - 2015-11-25 01:25 -0800
Re: A question on designated initializers Don Bruder <dakidd@sonic.net> - 2015-11-24 07:38 -0800
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-24 15:54 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-25 01:49 +0100
Re: A question on designated initializers Don Bruder <dakidd@sonic.net> - 2015-11-24 18:51 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-25 04:41 +0100
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-25 00:25 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-25 14:16 +0100
Re: A question on designated initializers Jon Rossen <jonr17@comcast.net> - 2015-11-25 17:30 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-26 03:03 +0100
Re: A question on designated initializers Don Bruder <dakidd@sonic.net> - 2015-11-25 09:08 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-11-25 18:41 +0100
Re: A question on designated initializers Don Bruder <dakidd@sonic.net> - 2015-12-02 14:37 -0800
Re: A question on designated initializers "Pascal J. Bourguignon" <pjb@informatimago.com> - 2015-12-03 00:58 +0100
Re: A question on designated initializers Don Bruder <dakidd@sonic.net> - 2015-11-24 18:29 -0800
Page 2 of 2 — ← Prev page 1 [2]
| From | "Pascal J. Bourguignon" <pjb@informatimago.com> |
|---|---|
| Date | 2015-11-25 01:49 +0100 |
| Message-ID | <87oaeivr7a.fsf@kuiper.lan.informatimago.com> |
| In reply to | #227 |
Jon Rossen <jonr17@comcast.net> writes:
> Ok....but backing up to the beginning of your paragraph:
> Hmmm, you lost me when you brought up your 'naked init' and said that
> it 'passes some reasonable defaults into the designated initializer'.
> The naked init in the current class just calls the current class'
> designated initializer and returns it. How does it pass some
> reasonable defaults *into it*??
"pass" as in "argument PASSing". We're assuming the designated
initializer will take at least one argument, since otherwise there's
would be little reason for it to exist (it would just be a renaming of
the init method). This passed argument is a default value specified by
-init.
> Might you be referring to the naked init that is the *superclass* of
> the current class? Certainly the super's init does that when you do
> self = [super init]. I just don't understand how the init at the
> current level feeds anything into the designated initializer at that
> same level.
-(id)init{return [self initWithWidth:1 andHeight:1];}
the defaults are 1 for the width, and 1 for the height.
> Speaking of nitpicks, in your code examples why don't you use
> (instancetype) as your return type?
I don't because I don't believe much in static typing. I'm more a
dynamic typing guy, so I'm happy with using id.
Also, I'm not in a hurry, I can wait 300 ms more to get the right
results.
>> You'll notice how close to identical the code is for both cases - The
>> critical consideration is that you ALWAYS want your class' "init" to
>> chain back to the root object, whether directly or indirectly.
>
> Not only are they close, aren't they basically *the exact same code*
> structurally? Meaning apart from the class-specific stuff that would
> be needed (different name of designated initializer, additional
> parameters, etc., etc.), the framework here is exactly the same as it
> was for the subclass (MyClass). I would *expect* it to be the same
> seeing that it's keeping the init chaining intact. Am I missing
> something or am I 'getting it'?
I don't agree with Don's code.
In general the subclass should call:
[super designatedInitializer:argument]
and not [super init], in its -designatedInitializer: method.
Notably, when the argument is given as a parameter to the subclass
-designatedInitializer:!
--
__Pascal Bourguignon__ http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk
[toc] | [prev] | [next] | [standalone]
| From | Don Bruder <dakidd@sonic.net> |
|---|---|
| Date | 2015-11-24 18:51 -0800 |
| Message-ID | <n337jb$6mt$2@dont-email.me> |
| In reply to | #229 |
In article <87oaeivr7a.fsf@kuiper.lan.informatimago.com>,
"Pascal J. Bourguignon" <pjb@informatimago.com> wrote:
> I don't agree with Don's code.
>
> In general the subclass should call:
> [super designatedInitializer:argument]
> and not [super init], in its -designatedInitializer: method.
>
> Notably, when the argument is given as a parameter to the subclass
> -designatedInitializer:!
OK, now *I'M* confused... Lemme go look at the code...
Now that I've gone and looked, I'm gonna update that to "I'm COMPLETELY
lost!" Please snatch in a copy of the code you're talking about and
annotate it to tell me specifically what it is you consider wrong with
it. I can't see anything (which is not to say it's impossible for me to
be wrong - only that if I am, I'm not seeing how or where based on what
you said), and I can't parse what you're saying up there in any way that
seems to make sense.
Never mind snatching it in... I've got it here, and I still can't see
what might be wrong.
???
> ---cut---
> #import <Cocoa/Cocoa.h>
>
> @interface MyClass : NSObject
> {
> // MyClass specific vars
> NSDictionary *myClassVars;
> }
> // And some method declarations
> -(MyClass *)designatedInitializer:(id)anyNeededParams;
> -(MyClass *)init;
> // More stuff will likely live here in a useful program.
> @end
> ---cut---
>
> And in your .m file:
> ---cut---
> #import "MyClass.h"
> @implementation MyClass
>
> -(MyClass *)designatedInitializer:(id)anyNeededParams
> {
> self = [super init]; // Invoke NSObject's init
>
> // Do MyClass-specific init
>
> // and return what self has become.
> return self;
> }
>
> -(MyClass *)init
> {
> // I'll assume defaultParams is set appropriately elsewhere
> return [self designatedInitializer:defaultParams];
> }
>
> // Any other methods MyClass needs follow
> @end
> ---cut---
> ---cut---
> #import "MyClass.h"
> @interface MySublass : MyClass
> {
> // MySublass specific vars
> NSDictionary *SubclassVar;
> }
> // And don't forget the method declarations
> -(MyClass *)designatedInitializer:(id)anyNeededParams;
> -(MyClass *)init;
>
> @end
> ---cut---
>
> And the .m file
> ---cut---
> #import "MySubclass.h"
> -(MySubclass *)designatedInitializer:(id)anyNeededParams
> {
> self = [super init]; // Invokes MyClass' init
>
> // Do MySubclass-specific init work
>
> // and return what self has become.
> return self;
> }
>
> -(MySubclass *)init
> {
> // I'll assume defaultMySubclassParams is set appropriately somewhere
> return [self designatedInitializer:defaultMySubclassParams];
> }
>
> // Any other methods MySubclass needs follow
>
> @end
> ---cut---
--
Security provided by Mssrs Smith and/or Wesson. Brought to you by the letter Q
[toc] | [prev] | [next] | [standalone]
| From | "Pascal J. Bourguignon" <pjb@informatimago.com> |
|---|---|
| Date | 2015-11-25 04:41 +0100 |
| Message-ID | <87d1uyvj8a.fsf@kuiper.lan.informatimago.com> |
| In reply to | #232 |
Don Bruder <dakidd@sonic.net> writes:
> In article <87oaeivr7a.fsf@kuiper.lan.informatimago.com>,
> "Pascal J. Bourguignon" <pjb@informatimago.com> wrote:
>
>
>> I don't agree with Don's code.
>>
>> In general the subclass should call:
>> [super designatedInitializer:argument]
>> and not [super init], in its -designatedInitializer: method.
>>
>> Notably, when the argument is given as a parameter to the subclass
>> -designatedInitializer:!
>
> OK, now *I'M* confused... Lemme go look at the code...
> Now that I've gone and looked, I'm gonna update that to "I'm COMPLETELY
> lost!" Please snatch in a copy of the code you're talking about and
> annotate it to tell me specifically what it is you consider wrong with
> it. I can't see anything (which is not to say it's impossible for me to
> be wrong - only that if I am, I'm not seeing how or where based on what
> you said), and I can't parse what you're saying up there in any way that
> seems to make sense.
>
> Never mind snatching it in... I've got it here, and I still can't see
> what might be wrong.
>
> ???
>
>> ---cut---
>> #import <Cocoa/Cocoa.h>
>>
>> @interface MyClass : NSObject
>> {
>> // MyClass specific vars
>> NSDictionary *myClassVars;
>> }
>> // And some method declarations
>> -(MyClass *)designatedInitializer:(id)anyNeededParams;
>> -(MyClass *)init;
>> // More stuff will likely live here in a useful program.
>> @end
>> ---cut---
>>
>> And in your .m file:
>> ---cut---
>> #import "MyClass.h"
>> @implementation MyClass
>>
>> -(MyClass *)designatedInitializer:(id)anyNeededParams
>> {
>> self = [super init]; // Invoke NSObject's init
>>
>> // Do MyClass-specific init
>>
>> // and return what self has become.
>> return self;
>> }
>>
>> -(MyClass *)init
>> {
>> // I'll assume defaultParams is set appropriately elsewhere
>> return [self designatedInitializer:defaultParams];
>> }
>>
>> // Any other methods MyClass needs follow
>> @end
>> ---cut---
>
>> ---cut---
>> #import "MyClass.h"
>> @interface MySublass : MyClass
>> {
>> // MySublass specific vars
>> NSDictionary *SubclassVar;
>> }
>> // And don't forget the method declarations
>> -(MyClass *)designatedInitializer:(id)anyNeededParams;
>> -(MyClass *)init;
>>
>> @end
>> ---cut---
>>
>> And the .m file
>> ---cut---
>> #import "MySubclass.h"
>> -(MySubclass *)designatedInitializer:(id)anyNeededParams
>> {
>> self = [super init]; // Invokes MyClass' init
This. The designated initializer of the super class (ie. the MyClass
class), is designatedInitializer: ; therefore this is the designated
initializer you must call from the subclass.
Since you call [super init], -[MyClass init] will send the
-designatedInitializer: message to self, which will call
-[MySubclass designatedInitializer:] and this will give an infinite
loop.
>> // Do MySubclass-specific init work
>>
>> // and return what self has become.
>> return self;
>> }
>>
>> -(MySubclass *)init
>> {
>> // I'll assume defaultMySubclassParams is set appropriately somewhere
>> return [self designatedInitializer:defaultMySubclassParams];
>> }
>>
>> // Any other methods MySubclass needs follow
>>
>> @end
>> ---cut---
--
__Pascal Bourguignon__ http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk
[toc] | [prev] | [next] | [standalone]
| From | Jon Rossen <jonr17@comcast.net> |
|---|---|
| Date | 2015-11-25 00:25 -0800 |
| Message-ID | <n33r9o$27f$1@news.albasani.net> |
| In reply to | #233 |
On 11/24/2015 7:41 PM, Pascal J. Bourguignon wrote:
> Don Bruder <dakidd@sonic.net> writes:
>
>> In article <87oaeivr7a.fsf@kuiper.lan.informatimago.com>,
>> "Pascal J. Bourguignon" <pjb@informatimago.com> wrote:
>>
>>
>>> I don't agree with Don's code.
>>>
>>> In general the subclass should call:
>>> [super designatedInitializer:argument]
>>> and not [super init], in its -designatedInitializer: method.
>>>
>>> Notably, when the argument is given as a parameter to the subclass
>>> -designatedInitializer:!
>>
>> OK, now *I'M* confused... Lemme go look at the code...
>> Now that I've gone and looked, I'm gonna update that to "I'm COMPLETELY
>> lost!" Please snatch in a copy of the code you're talking about and
>> annotate it to tell me specifically what it is you consider wrong with
>> it. I can't see anything (which is not to say it's impossible for me to
>> be wrong - only that if I am, I'm not seeing how or where based on what
>> you said), and I can't parse what you're saying up there in any way that
>> seems to make sense.
>>
>> Never mind snatching it in... I've got it here, and I still can't see
>> what might be wrong.
>>
>> ???
>>
>>> ---cut---
>>> #import <Cocoa/Cocoa.h>
>>>
>>> @interface MyClass : NSObject
>>> {
>>> // MyClass specific vars
>>> NSDictionary *myClassVars;
>>> }
>>> // And some method declarations
>>> -(MyClass *)designatedInitializer:(id)anyNeededParams;
>>> -(MyClass *)init;
>>> // More stuff will likely live here in a useful program.
>>> @end
>>> ---cut---
>>>
>>> And in your .m file:
>>> ---cut---
>>> #import "MyClass.h"
>>> @implementation MyClass
>>>
>>> -(MyClass *)designatedInitializer:(id)anyNeededParams
>>> {
>>> self = [super init]; // Invoke NSObject's init
>>>
>>> // Do MyClass-specific init
>>>
>>> // and return what self has become.
>>> return self;
>>> }
>>>
>>> -(MyClass *)init
>>> {
>>> // I'll assume defaultParams is set appropriately elsewhere
>>> return [self designatedInitializer:defaultParams];
>>> }
>>>
>>> // Any other methods MyClass needs follow
>>> @end
>>> ---cut---
>>
>>> ---cut---
>>> #import "MyClass.h"
>>> @interface MySublass : MyClass
>>> {
>>> // MySublass specific vars
>>> NSDictionary *SubclassVar;
>>> }
>>> // And don't forget the method declarations
>>> -(MyClass *)designatedInitializer:(id)anyNeededParams;
>>> -(MyClass *)init;
>>>
>>> @end
>>> ---cut---
>>>
>>> And the .m file
>>> ---cut---
>>> #import "MySubclass.h"
>>> -(MySubclass *)designatedInitializer:(id)anyNeededParams
>>> {
>>> self = [super init]; // Invokes MyClass' init
>
> This. The designated initializer of the super class (ie. the MyClass
> class), is designatedInitializer: ; therefore this is the designated
> initializer you must call from the subclass.
> Since you call [super init], -[MyClass init] will send the
> -designatedInitializer: message to self, which will call
> -[MySubclass designatedInitializer:] and this will give an infinite
> loop.
Pascal, I also noticed that you and Don had different code for the
designated initializer and forgot to ask about it; thanks for bringing
it up.
Don uses: self = [super init];
while you use: self = [super designatedInitializer];
I'm not sure if I'm following your code path here. If someone uses
Don's method, [super init] is called, and it returns a
designatedInitializer message to self. Then you lose me when you say
'which will call [MySubClass designatedInitializer]' which as you say
will give an infinite loop. I don't understand the call to [MySubClass
designatedInitializer].
It was my understanding you end up traversing *up* the inheritance
branch to the root class: You call super's init, it returns a message
to self from *super's* designatedIniializer which has a call to *its*
[super init], which returns a message to self from the designated
initializer at its level, and the pattern keeps repeating until you get
up to the end. Everything that is inherited by the current class gets
initialized.
Then after self = [super init];
You make sure that self exists (i.e. initialization was successful): if
(self)
{ put your init code in the code block of the if statement }
So essentially the first part where you state: self = [super init]
serves to go back up the inheritance branch and initialize all the
inherited stuff. This is how the stuff is all 'chained' together. while
the new init code you put in the if() statement is the new, current
class specific init code specific to the current class.
If my understanding of this is flawed, please let me know where.
>
>
>>> // Do MySubclass-specific init work
>>>
>>> // and return what self has become.
>>> return self;
>>> }
>>>
>>> -(MySubclass *)init
>>> {
>>> // I'll assume defaultMySubclassParams is set appropriately somewhere
>>> return [self designatedInitializer:defaultMySubclassParams];
>>> }
>>>
>>> // Any other methods MySubclass needs follow
>>>
>>> @end
>>> ---cut---
>
[toc] | [prev] | [next] | [standalone]
| From | "Pascal J. Bourguignon" <pjb@informatimago.com> |
|---|---|
| Date | 2015-11-25 14:16 +0100 |
| Message-ID | <878u5muslu.fsf@kuiper.lan.informatimago.com> |
| In reply to | #234 |
Jon Rossen <jonr17@comcast.net> writes:
> Pascal, I also noticed that you and Don had different code for the
> designated initializer and forgot to ask about it; thanks for bringing
> it up.
>
> Don uses: self = [super init];
> while you use: self = [super designatedInitializer];
>
> I'm not sure if I'm following your code path here. If someone uses
> Don's method, [super init] is called, and it returns a
> designatedInitializer message to self. Then you lose me when you say
> which will call [MySubClass designatedInitializer]' which as you say
> will give an infinite loop. I don't understand the call to
> [MySubClass designatedInitializer].
You have to understand the difference between a MESSAGE and a METHOD.
To send a message we indicate:
- a recipient object for that message, (eg. self);
- a selector, (eg. designatedInitializer:);
- arguments, (eg. defaultValue).
Sending a message is therefore written:
[self designatedInitializer:defaultValue]
The selector is denoted as designatedInitializer:
In code, we'd use the SEL macro:
SEL(designatedInitializer:)
When sending a message is executed, there is a dispatching to a method.
That is, at run-time, the Objective-C runtime will try to find a method
matching the selector for the recipient object (which can also be a
class, classes are objects).
Dispatching works like this:
- find the class of the object (if it's a class, find the metaclass);
- search a method for the selector in that class.
- if there is no method for the selector in that class, then search in
the superclass, and so on.
When we send a message to super, we start the search directly from the
superclass, instead of starting from the class.
So when a method is found, such as -[SomeClass designatedInitializer:]
then it is called. A method is basically a C function with two
additionnal parameters (a selector _cmd, and the recipient self).
Notice that methods are denoted by:
- a sign - for instance methods (stored in the class), + for class
methods (stored in the metaclass).
- a class name,
- a designator.
-[SomeClass designatedInitializer:]
So you can have two methods:
-[MyClass designatedInitializer:]
-[MySubClass designatedInitializer:]
and when you send a designatedInitializer: message:
[self designatedInitializer:42]
one or the other method may be called first, depending on the class of
self.
The class of self is not necessarily the class of the method being
executed!
Usually, the class of self is a SUBCLASS of the class of the method
being executed.
The problem with Don's code is that there are four methods:
-[MyClass init]
[self designatedInitializer:default]
-[MyClass designatedInitializer:]
…
-[MySubClass init]
[super init]
-[MySubClass designatedInitializer:]
[super designatedInitializer:default]
[MySubclass alloc] returns an instance of MySubClass.
The only instance we'll have is of the class MySubClass.
Sending the message [[MySubclass alloc] init]
sends the init message to an instance of the class MySubClass.
So we call the method -[MySubClass init], passing the instance of the
class MySubClass.
which sends the message init to super, that is, to the same instance of
the class MySubClass, but searching the method -init starting from the
superclass.
So we call the method -[MyClass init], passing the instance of the
class MySubClass.
This sends the designatedInitializer: message to this instance of the
class MySubClass.
So we search a -designatedInitializer: method starting from the class
MySubClass, and we find -[MySubClass designatedInitializer:]
This sends the message [super init], so we search an -init method from
the superclass and find -[MyClass init], passing the instance of the
class MySubClass.
This sends the designatedInitializer: message to this instance of the
class MySubClass.
So we search a -designatedInitializer: method starting from the class
MySubClass, and we find -[MySubClass designatedInitializer:]
This sends the message [super init], so we search an -init method from
the superclass and find -[MyClass init], passing the instance of the
class MySubClass.
This sends the designatedInitializer: message to this instance of the
class MySubClass.
So we search a -designatedInitializer: method starting from the class
MySubClass, and we find -[MySubClass designatedInitializer:]
This sends the message [super init], so we search an -init method from
the superclass and find -[MyClass init], passing the instance of the
class MySubClass.
This sends the designatedInitializer: message to this instance of the
class MySubClass.
So we search a -designatedInitializer: method starting from the class
MySubClass, and we find -[MySubClass designatedInitializer:]
This sends the message [super init], so we search an -init method from
the superclass and find -[MyClass init],
etc.
The whole point of OOP and inheritance, is to be able send a message to
an object without knowing at compilation time what class or subclass
this object will be. So the actual method called when we send this
message, is determined at run-time, and may be a method of a subclass
that wasn't even imagined when we wrote this message sending.
When we have:
@implementation MyClass
-(id)init{
return [self designatedInitializer:42];
}
@end
the only raison-d'être of this method, is to call the method of the
subclass of MyClass of which self is an instance.
Because we know, when we write MyClass, that we don't know what the
future has in stock for us. We know that the customer will come with
some crazy requirements, which makes -[MyClass designatedInitializer:]
completely inadapted and outdated.
Therefore when the crazy customer comes with his crazy requirements, we
will write a subclass that will do the right thing, by implementing a
-[CrazyCustomerSubclass designatedInitializer:] method, knowing that the
rest of the MyClass code will still work, because everytime it has to
rely on some specific behavior, it will send a message to the object
that will be dispatched to the right method according to the class of
that object.
--
__Pascal Bourguignon__ http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk
[toc] | [prev] | [next] | [standalone]
| From | Jon Rossen <jonr17@comcast.net> |
|---|---|
| Date | 2015-11-25 17:30 -0800 |
| Message-ID | <n35nc1$48e$1@news.albasani.net> |
| In reply to | #236 |
Pascal,
I'm starting to get hopelessly confused.
The following are parts of your response that I think address where I
was (or still am) confused
> - if there is no method for the selector in that class, then search in
> the superclass, and so on.
Right, I'm generally already familiar with the search pattern here.
> When we send a message to super, we start the search directly from the
> superclass, instead of starting from the class.
Ok, I think this may be were my problem has been. You are saying here
that if you send a message to super, then the *super class* is where the
search begins, *not* from the current class. This seems to put a
different spin on what you said just above, where the search starts in
the current class.
> So when a method is found, such as -[SomeClass designatedInitializer:]
> then it is called. A method is basically a C function with two
> additionnal parameters (a selector _cmd, and the recipient self).
>
> Notice that methods are denoted by:
>
> - a sign - for instance methods (stored in the class), + for class
> methods (stored in the metaclass).
> - a class name,
> - a designator.
>
> -[SomeClass designatedInitializer:]
>
>
> So you can have two methods:
>
> -[MyClass designatedInitializer:]
> -[MySubClass designatedInitializer:]
Ok, got it. Just a nitpick...these are instance methods, not class
methods so technically shouldn't this example be something like:
[myClassObject designatedInitializer]
[mySubclassObject designatedInitializer]
...or does the '-' you have as a prefix serve to state this and the
examples (names used) are supposed to be taken abstractly?
> and when you send a designatedInitializer: message:
>
> [self designatedInitializer:42]
>
> one or the other method may be called first, depending on the class of
> self.
The version that is called first is the version that is in self's class.
Please tell me that what I have said is correct, or else I'm going to
kill myself after I destroy my computer. :-)
> The class of self is not necessarily the class of the method being
> executed!
This statement seems at odds at the one right above that I commented on.
What are you saying here? You seem to be saying that the class of
self may not be the class of the method being executed. But I think I
know why you are saying this. You seem to be implying something here
but you are not explicitly giving a specific scenario.
Is this statement related to the fact that the search for the method
executed first could be in *super's* class? This is what you touched on
a few comments above. In other words in that scenario (if I'm
understanding that correctly), a different method than the one in self's
class would be executed. Is this what you are saying here?
> Usually, the class of self is a SUBCLASS of the class of the method
> being executed.
Ok, this is the scenario that is at the heart of what I was saying just
directly above, or at least trying to.
>
> The problem with Don's code is that there are four methods:
>
> -[MyClass init]
> [self designatedInitializer:default]
>
> -[MyClass designatedInitializer:]
> …
>
> -[MySubClass init]
> [super init]
>
> -[MySubClass designatedInitializer:]
> [super designatedInitializer:default]
>
>
> [MySubclass alloc] returns an instance of MySubClass.
> The only instance we'll have is of the class MySubClass.
>
> Sending the message [[MySubclass alloc] init]
>
> sends the init message to an instance of the class MySubClass.
>
> So we call the method -[MySubClass init], passing the instance of the
> class MySubClass.
>
> which sends the message init to super, that is, to the same instance of
> the class MySubClass, but searching the method -init starting from the
> superclass.
>
> So we call the method -[MyClass init], passing the instance of the
> class MySubClass.
>
> This sends the designatedInitializer: message to this instance of the
> class MySubClass.
>
> So we search a -designatedInitializer: method starting from the class
> MySubClass, and we find -[MySubClass designatedInitializer:]
>
> This sends the message [super init], so we search an -init method from
> the superclass and find -[MyClass init], passing the instance of the
> class MySubClass.
>
> This sends the designatedInitializer: message to this instance of the
> class MySubClass.
>
> So we search a -designatedInitializer: method starting from the class
> MySubClass, and we find -[MySubClass designatedInitializer:]
>
> This sends the message [super init], so we search an -init method from
> the superclass and find -[MyClass init], passing the instance of the
> class MySubClass.
>
> This sends the designatedInitializer: message to this instance of the
> class MySubClass.
>
> So we search a -designatedInitializer: method starting from the class
> MySubClass, and we find -[MySubClass designatedInitializer:]
>
> This sends the message [super init], so we search an -init method from
> the superclass and find -[MyClass init], passing the instance of the
> class MySubClass.
>
> This sends the designatedInitializer: message to this instance of the
> class MySubClass.
>
> So we search a -designatedInitializer: method starting from the class
> MySubClass, and we find -[MySubClass designatedInitializer:]
>
> This sends the message [super init], so we search an -init method from
> the superclass and find -[MyClass init],
>
> etc.
>
>
>
>
> The whole point of OOP and inheritance, is to be able send a message to
> an object without knowing at compilation time what class or subclass
> this object will be. So the actual method called when we send this
> message, is determined at run-time, and may be a method of a subclass
> that wasn't even imagined when we wrote this message sending.
>
> When we have:
>
> @implementation MyClass
> -(id)init{
> return [self designatedInitializer:42];
> }
> @end
>
> the only raison-d'être of this method, is to call the method of the
> subclass of MyClass of which self is an instance.
>
> Because we know, when we write MyClass, that we don't know what the
> future has in stock for us. We know that the customer will come with
> some crazy requirements, which makes -[MyClass designatedInitializer:]
> completely inadapted and outdated.
>
> Therefore when the crazy customer comes with his crazy requirements, we
> will write a subclass that will do the right thing, by implementing a
> -[CrazyCustomerSubclass designatedInitializer:] method, knowing that the
> rest of the MyClass code will still work, because everytime it has to
> rely on some specific behavior, it will send a message to the object
> that will be dispatched to the right method according to the class of
> that object.
>
[toc] | [prev] | [next] | [standalone]
| From | "Pascal J. Bourguignon" <pjb@informatimago.com> |
|---|---|
| Date | 2015-11-26 03:03 +0100 |
| Message-ID | <87r3jdtt2p.fsf@kuiper.lan.informatimago.com> |
| In reply to | #239 |
Jon Rossen <jonr17@comcast.net> writes:
>> So you can have two methods:
>>
>> -[MyClass designatedInitializer:]
>> -[MySubClass designatedInitializer:]
>
> Ok, got it. Just a nitpick...these are instance methods, not class
> methods so technically shouldn't this example be something like:
> [myClassObject designatedInitializer]
> [mySubclassObject designatedInitializer]
No. The point is that both methods can be called for the same object!
-[MyClass designatedInitializer:]
-[MySubClass designatedInitializer:]
For example:
@implementation MySubClass
-(id)init {
// you can write:
self=[self designatedInitializer:42];
// or you can write:
self=[super designatedInitializer:42];
return self;
}
@end
If you send the message to self, then it's the method:
-[MySubClass designatedInitializer:]
that is called, and if you send the message to super, then
it's the method:
-[MyClass designatedInitializer:]
that is called.
> ...or does the '-' you have as a prefix serve to state this and the
> examples (names used) are supposed to be taken abstractly?
Yes, the notation -[MyClass designatedInitializer:]
or: +[NSObject alloc]
is not source code. They are the name of actual methods.
>> and when you send a designatedInitializer: message:
>>
>> [self designatedInitializer:42]
>>
>> one or the other method may be called first, depending on the class of
>> self.
>
> The version that is called first is the version that is in self's
> class. Please tell me that what I have said is correct, or else I'm
> going to kill myself after I destroy my computer. :-)
If the class of self has such an instance method, yes.
If self is an instance of a sub sub class that doesn't define a method
for the selector -designatedInitializer: then it will be the method in
the next superclass, ie. MySubClass.
>> The class of self is not necessarily the class of the method being
>> executed!
>
> This statement seems at odds at the one right above that I commented
> on. What are you saying here? You seem to be saying that the class of
> self may not be the class of the method being executed.
Yes, this is what I'm saying.
> But I think I
> know why you are saying this. You seem to be implying something here
> but you are not explicitly giving a specific scenario.
Indeed. You need to imagine new examples.
Again, I assume that you wrote code, and that you inserted printing of
the class of the instance in the various methods.
Add lines such as:
@implementation MyClass
-… {
…
NSLog(@"in method %@ of class %@, class of self = %@",
NSStringFromSelector(_cmd),
@"MyClass",
[self className]);
…
}
@end
@implementation MySubClass
-… {
…
NSLog(@"in method %@ of class %@, class of self = %@",
NSStringFromSelector(_cmd),
@"MySubClass", // *** <- in subclass
[self className]);
…
}
@end
in each method and send a message and see
> Is this statement related to the fact that the search for the method
> executed first could be in *super's* class?
Nope. The recipient is self, so the search starts in self's class.
> This is what you touched on a few comments above. In other words in
> that scenario (if I'm understanding that correctly), a different
> method than the one in self's class would be executed. Is this what
> you are saying here?
No. I'm saying that self could be an instance of a different class than
the class of the method where self is used. That is, it could be an
instance of a subclass, or even possibly of an entirely different class.
This is why in the initializer you assign self. The superclass
initializer may actually unallocate self, and allocate a new instance of
a completely different class (as long as that instances of this
different class can receive the same set of messages).
When you have class clusters, you will have normally a subclass so it
won't be "strange". But there are other tricks, such as having proxy
objects. Then the class of the object is not even a subclass, but an
entirely different class. But you can ignore this for the moment, since
the proxy object will respond to the same messages as a normal object.
--
__Pascal Bourguignon__ http://www.informatimago.com/
“The factory of the future will have only two employees, a man and a
dog. The man will be there to feed the dog. The dog will be there to
keep the man from touching the equipment.” -- Carl Bass CEO Autodesk
[toc] | [prev] | [next] | [standalone]
| From | Don Bruder <dakidd@sonic.net> |
|---|---|
| Date | 2015-11-25 09:08 -0800 |
| Message-ID | <n34ppq$km8$1@dont-email.me> |
| In reply to | #233 |
In article <87d1uyvj8a.fsf@kuiper.lan.informatimago.com>,
"Pascal J. Bourguignon" <pjb@informatimago.com> wrote:
> Don Bruder <dakidd@sonic.net> writes:
>
> > In article <87oaeivr7a.fsf@kuiper.lan.informatimago.com>,
> > "Pascal J. Bourguignon" <pjb@informatimago.com> wrote:
> >
> >
> >> I don't agree with Don's code.
> >>
> >> In general the subclass should call:
> >> [super designatedInitializer:argument]
> >> and not [super init], in its -designatedInitializer: method.
> >>
> >> Notably, when the argument is given as a parameter to the subclass
> >> -designatedInitializer:!
> >
> > OK, now *I'M* confused... Lemme go look at the code...
> > Now that I've gone and looked, I'm gonna update that to "I'm COMPLETELY
> > lost!" Please snatch in a copy of the code you're talking about and
> > annotate it to tell me specifically what it is you consider wrong with
> > it. I can't see anything (which is not to say it's impossible for me to
> > be wrong - only that if I am, I'm not seeing how or where based on what
> > you said), and I can't parse what you're saying up there in any way that
> > seems to make sense.
> >
> > Never mind snatching it in... I've got it here, and I still can't see
> > what might be wrong.
> >
> > ???
> >
> >> ---cut---
> >> #import <Cocoa/Cocoa.h>
> >>
> >> @interface MyClass : NSObject
> >> {
> >> // MyClass specific vars
> >> NSDictionary *myClassVars;
> >> }
> >> // And some method declarations
> >> -(MyClass *)designatedInitializer:(id)anyNeededParams;
> >> -(MyClass *)init;
> >> // More stuff will likely live here in a useful program.
> >> @end
> >> ---cut---
> >>
> >> And in your .m file:
> >> ---cut---
> >> #import "MyClass.h"
> >> @implementation MyClass
> >>
> >> -(MyClass *)designatedInitializer:(id)anyNeededParams
> >> {
> >> self = [super init]; // Invoke NSObject's init
> >>
> >> // Do MyClass-specific init
> >>
> >> // and return what self has become.
> >> return self;
> >> }
> >>
> >> -(MyClass *)init
> >> {
> >> // I'll assume defaultParams is set appropriately elsewhere
> >> return [self designatedInitializer:defaultParams];
> >> }
> >>
> >> // Any other methods MyClass needs follow
> >> @end
> >> ---cut---
> >
> >> ---cut---
> >> #import "MyClass.h"
> >> @interface MySublass : MyClass
> >> {
> >> // MySublass specific vars
> >> NSDictionary *SubclassVar;
> >> }
> >> // And don't forget the method declarations
> >> -(MyClass *)designatedInitializer:(id)anyNeededParams;
> >> -(MyClass *)init;
> >>
> >> @end
> >> ---cut---
> >>
> >> And the .m file
> >> ---cut---
> >> #import "MySubclass.h"
> >> -(MySubclass *)designatedInitializer:(id)anyNeededParams
> >> {
> >> self = [super init]; // Invokes MyClass' init
>
> This. The designated initializer of the super class (ie. the MyClass
> class), is designatedInitializer: ; therefore this is the designated
> initializer you must call from the subclass.
> Since you call [super init], -[MyClass init] will send the
> -designatedInitializer: message to self, which will call
> -[MySubclass designatedInitializer:] and this will give an infinite
> loop.
You'll pardon my skepticism, I hope - I'm an empiricist at heart...
Gonna do some playing and see what I can come up with, but at this
stage, what you're saying is so *TOTALLY* counterintuitive I can't even
start to accept it. Everything I've ever grasped about
inheritance/subclassing tells me that I'm not supposed to "need" to know
the internals of the class I'm deriving from - it's a black box. So long
as you do thus and so, your subclass will work. "Thus and so" in this
case meaning "Make damn sure you chain back to the root object by
calling your superclass' init method or all hell's gonna break loose".
I'll get back to this after I've done some tinkering...
--
Security provided by Mssrs Smith and/or Wesson. Brought to you by the letter Q
[toc] | [prev] | [next] | [standalone]
| From | "Pascal J. Bourguignon" <pjb@informatimago.com> |
|---|---|
| Date | 2015-11-25 18:41 +0100 |
| Message-ID | <874mgaugc9.fsf@kuiper.lan.informatimago.com> |
| In reply to | #237 |
Don Bruder <dakidd@sonic.net> writes: > You'll pardon my skepticism, I hope - I'm an empiricist at heart... I assumed so much, and therefore I assumed you already ran the code, and saw the infinite loop for yourself! > Gonna do some playing and see what I can come up with, but at this > stage, what you're saying is so *TOTALLY* counterintuitive I can't even > start to accept it. Everything I've ever grasped about > inheritance/subclassing tells me that I'm not supposed to "need" to know > the internals of the class I'm deriving from - it's a black box. So long > as you do thus and so, your subclass will work. "Thus and so" in this > case meaning "Make damn sure you chain back to the root object by > calling your superclass' init method or all hell's gonna break loose". Well, either your class is "documented", with a class invariant and a set of pre- and post- conditions for each method, or you have to know the internals. Since you never find those invariants and sets of pre- and post-conditions documented, you never know, and always have to know the internals, which indeed, is a very bad situation. -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk
[toc] | [prev] | [next] | [standalone]
| From | Don Bruder <dakidd@sonic.net> |
|---|---|
| Date | 2015-12-02 14:37 -0800 |
| Message-ID | <n3nrna$f6$1@dont-email.me> |
| In reply to | #238 |
In article <874mgaugc9.fsf@kuiper.lan.informatimago.com>, "Pascal J. Bourguignon" <pjb@informatimago.com> wrote: > Don Bruder <dakidd@sonic.net> writes: > > > You'll pardon my skepticism, I hope - I'm an empiricist at heart... > > I assumed so much, and therefore I assumed you already ran the code, and > saw the infinite loop for yourself! Been gone longer than planned, but back to the home machine now... Nope, at that point, hadn't tried running it. Have now. And am gobsmacked! Also educated - This explains a situation I had a few years back when I tried to subclass from one of the "NSXxxx" classes that come with cocoa - I got *EXACTLY* the same behavior back then as what I saw when I tried running the code we've been talking about, and never did bother to chase down the how/why. Ended up just tacking a category on the class rather than doing an actual subclass, and things worked just fine. > > > > Gonna do some playing and see what I can come up with, but at this > > stage, what you're saying is so *TOTALLY* counterintuitive I can't even > > start to accept it. Everything I've ever grasped about > > inheritance/subclassing tells me that I'm not supposed to "need" to know > > the internals of the class I'm deriving from - it's a black box. So long > > as you do thus and so, your subclass will work. "Thus and so" in this > > case meaning "Make damn sure you chain back to the root object by > > calling your superclass' init method or all hell's gonna break loose". > > Well, either your class is "documented", with a class invariant > and a set of pre- and post- conditions for each method, or you have to > know the internals. > > Since you never find those invariants and sets of pre- and > post-conditions documented, you never know, and always have to know the > internals, which indeed, is a very bad situation. Yeah... it does a serious number on the whole "A class stands alone, you can treat it as a black box" concept that was (until now...) my understanding of one of the main points of OOP. So now, I'm gonna have to get my head around how to cope with this "breakage"... -- Security provided by Mssrs Smith and/or Wesson. Brought to you by the letter Q
[toc] | [prev] | [next] | [standalone]
| From | "Pascal J. Bourguignon" <pjb@informatimago.com> |
|---|---|
| Date | 2015-12-03 00:58 +0100 |
| Message-ID | <87610gqu6i.fsf@kuiper.lan.informatimago.com> |
| In reply to | #245 |
Don Bruder <dakidd@sonic.net> writes: >> Well, either your class is "documented", with a class invariant >> and a set of pre- and post- conditions for each method, or you have to >> know the internals. >> >> Since you never find those invariants and sets of pre- and >> post-conditions documented, you never know, and always have to know the >> internals, which indeed, is a very bad situation. > > Yeah... it does a serious number on the whole "A class stands alone, you > can treat it as a black box" concept that was (until now...) my > understanding of one of the main points of OOP. Well, the system of class invariant and pre-/post-conditions is what defines the black box. What it says, is that if you ensure that the pre-conditions are met, then when you send a message, the post-condition will be ensure by the black box. Usually, the post-condition is a useful value or side effect, and the specification of the pre- and post-condition establish contract that clearly indicates the responsibilities of the black box and the user of the black box. > So now, I'm gonna have to get my head around how to cope with this > "breakage"... Of course, if you have constraining pre-conditions, as long as they are well documented, the function caller or message sender will be able to ensure that the pre-condition is met, and everything will work nicely. Alternatively, if your pre-conditions are true, then the caller or sender will be able to interact with your objects in any way it wants, and everything should work nicely. The problem is when there are pre-conditions that are not documented. In that case, indeed the black box notion breaks, because you cannot use it anymore without looking what's inside the box, how the class is implemented, and then making assumption about what you can do with it or not. The assumptions are valid while you use the exact same white box, but if you replace it with another implementation (or a black-box subclass), then your assumptions might reveal inadequate and your software will break. Notice that documentations of frameworks (sets of classes) are usually not that formal; they don't explicitely write down the pre-/post-conditions for each methods; some general indications are given in English, and you may infer some pre-/post-conditions and class invariant, but you may also err, and this is what makes it rather difficult to use those frameworks. So you should not necessarily follow those examples… https://en.wikipedia.org/wiki/Design_by_contract -- __Pascal Bourguignon__ http://www.informatimago.com/ “The factory of the future will have only two employees, a man and a dog. The man will be there to feed the dog. The dog will be there to keep the man from touching the equipment.” -- Carl Bass CEO Autodesk
[toc] | [prev] | [next] | [standalone]
| From | Don Bruder <dakidd@sonic.net> |
|---|---|
| Date | 2015-11-24 18:29 -0800 |
| Message-ID | <n336ad$6mt$1@dont-email.me> |
| In reply to | #227 |
In article <n32tc0$hik$1@news.albasani.net>,
Jon Rossen <jonr17@comcast.net> wrote:
> < A bunch of previous stuff cut out...new comments inline below>
> thx -jonR
>
> >> Don, Thanks so much for your response with all of this info; I really
> >> appreciate it. It is the perfect combination of theory and practical
> >> info. You are right, I sort of understand the chaining mechanism in how
> >> things unfold in the class hierarchy. The construct that you
> >> illustrated here with the default values used by the 'convenience' init
> >> methods is something I came across earlier today coincidentally, but
> >> your explanation was much more specific, to the point and not obfuscated
> >> by vague implications. I have a few more questions:
> >>
> >> 1. Just a workflow question: Re: the 'convenience' init methods that
> >> may be helpful to get objects accompany the designated one: Is it
> >> typical for a developer when building a class to add the 'convenience'
> >> init methods later on or sort of on an 'as needed' basis depending? I'm
> >> not asking this as to what's good or bad, but am assuming it just
> >> depends on the situation and in your experience how does this usually
> >> play out?
> >
> > I can't speak for anyone but myself, so YMMV...
> > Personally, I code a "designated" initializer that takes appropriate
> > inputs and uses them to handle *EVERYTHING*, to start with, then a
> > "naked init" ("-(MyClass *)init") method that passes some reasonable
> > defaults into the designated initializer. Often, but nowhere near
> > always, that's all that's needed. (Or more accurately, it's *ALWAYS* all
> > that's *NEEDED*, but it's only occasionally all that's *WANTED*, if you
> > understand the distinction) If, as the project progresses, and I notice
> > a need for them, I might add more convenience initializers. The decision
> > to add more convenience initializers or not is totally dependent on the
> > needs of the specific project - In one project, I might code the
> > designated initializer, the cover for "init", and several variations, as
> > needed. In another, I might not code anything except the designated
> > initializer, and a cover for "plain" init so that any subclasses I (or
> > someone else...) might cook up later will chain back up the line
> > properly when hit with a "[super init]". Either way, if somebody
> > subclasses from your class, they come in with the expectation that doing
> > "[super init]" will do the right thing (by calling the root object's
> > init method - perhaps directly, or perhaps through a very long and
> > complex chain of calls, but it'll happen eventually)
>
> Ok....but backing up to the beginning of your paragraph:
> Hmmm, you lost me when you brought up your 'naked init' and said that it
> 'passes some reasonable defaults into the designated initializer'. The
> naked init in the current class just calls the current class' designated
> initializer and returns it. How does it pass some reasonable defaults
> *into it*?? Might you be referring to the naked init that is the
> *superclass* of the current class? Certainly the super's init does that
> when you do self = [super init]. I just don't understand how the init
> at the current level feeds anything into the designated initializer at
> that same level.
(I'm going to proceed assuming we're both talking about the code snips
that are down below, not anything that might have been mentioned in the
pruned material)
When the naked init makes the call to the DI, it passes an NSDictionary
of default values (which I assume gets set up elsewhere)
>
>
> >> 2. Ok, hopefully this question won't open up a can of worms. What about
> >> sub-classes? I guess this is a two part question:
> >> a) If there's a sub-class that doesn't particularly need it's own
> >> class designated initializer, it could just use it's super's designated
> >> initializer, correct? If so, is this a common design pattern?
> >
> > At least in theory, yes, that's correct. As for how common it is...
> > <shrug> No clue - I've never actually taken the time to think about it.
> >
> > (minor nitpick: "it's" is a contraction meaning "it is" - You're looking
> > for the possessive form: "its" - "that which belongs to it". Ain't it
> > wonderful how consistent the english language is? :) )
>
> Yeah, yeah, I know all of that; it was purely a typo due to being tired.
> When I get tired I have a tendency to spell fenetically :-) and little
> details drop off by the wayside. But great nitpick...I'd give it a 9
> out of 10 at least. :-)
The finest (and possibly most maddening!) example of apostrophe abuse
I've ever encountered was a roadside stand with a sign I used to have to
drive by at least twice daily - Half a sheet of plywood painted sky blue
then in wonderful, almost calligraphy-like script, hand painted in
screaming brilliant red, so it gave the illusion of "vibrating":
FRESH
EGG'S
4-SALE!
AUGH!!!!!! <facepalm - really really hard!>
>
> Speaking of nitpicks, in your code examples why don't you use
> (instancetype) as your return type?
Uh... 'Cuz I'm not returning an instance type, I'm returning an instance
of a class?
>
> >
> >> b) If the sub-class *does* need a designated initializer, I suppose it
> >> could do an override of the super's version and that would be ok.
> >> However, I would think that any additional initialization would have to
> >> be done via assessor methods as the method names would have to be the
> >> same.
> >
> > Sounds right... I THINK - Assuming you're asking what I think you are.
>
> OK.
>
> > If you're expecting to be subclassing off your subclass, then write your
> > "first level" subclass - let's call it MyClass - like so:
> > (I'm assuming you're on a Mac, so you'll probably be subclassing it from
> > NSObject)
>
>
> >
> > Your .h file has (at least - perhaps MUCH more) in it:
> > ---cut---
> > #import <Cocoa/Cocoa.h>
> >
> > @interface MyClass : NSObject
> > {
> > // MyClass specific vars
> > NSDictionary *myClassVars;
> > }
> > // And some method declarations
> > -(MyClass *)designatedInitializer:(id)anyNeededParams;
> > -(MyClass *)init;
> > // More stuff will likely live here in a useful program.
> > @end
> > ---cut---
> >
> > And in your .m file:
> > ---cut---
> > #import "MyClass.h"
> > @implementation MyClass
> >
> > -(MyClass *)designatedInitializer:(id)anyNeededParams
> > {
> > self = [super init]; // Invoke NSObject's init
> >
> > // Do MyClass-specific init
> >
> > // and return what self has become.
> > return self;
> > }
> >
> > -(MyClass *)init
> > {
> > // I'll assume defaultParams is set appropriately elsewhere
> > return [self designatedInitializer:defaultParams];
> > }
> >
> > // Any other methods MyClass needs follow
> > @end
> > ---cut---
> >
> > Notice that all init does is call the instance's designated initializer
> > with default params. Which in turn calls [super init] (NSObject's, in
> > this case) before using the parameters it gets passed. You get the rest
> > of your MyClass going, ship the project, and make a few bucks.
>
> Right. This code example is pretty much the same example you showed me
> the other day, and BTW, is consistent with my understanding of how to do
> this. So, there's nothing new here with respect to the other day's
> example, right?
Other than being "more refined", no, not really - hang with me till
after the next blob...
>
> >
> > Time passes, and a project you just got handed wants something very
> > nearly identical to MyClass, but with a couple little additions and
> > tweaks. You decide to subclass from MyClass to make a new class of
> > object - The MySubclass
> >
> > You toss together a quick .h file:
> > ---cut---
> > #import "MyClass.h"
> > @interface MySublass : MyClass
> > {
> > // MySublass specific vars
> > NSDictionary *SubclassVar;
> > }
> > // And don't forget the method declarations
> > -(MyClass *)designatedInitializer:(id)anyNeededParams;
> > -(MyClass *)init;
> >
> > @end
> > ---cut---
> >
> > And the .m file
> > ---cut---
> > #import "MySubclass.h"
> > -(MySubclass *)designatedInitializer:(id)anyNeededParams
> > {
> > self = [super init]; // Invokes MyClass' init
> >
> > // Do MySubclass-specific init work
> >
> > // and return what self has become.
> > return self;
> > }
> >
> > -(MySubclass *)init
> > {
> > // I'll assume defaultMySubclassParams is set appropriately somewhere
> > return [self designatedInitializer:defaultMySubclassParams];
> > }
> >
> > // Any other methods MySubclass needs follow
> >
> > @end
> > ---cut---
> >
> > You'll notice how close to identical the code is for both cases - The
> > critical consideration is that you ALWAYS want your class' "init" to
> > chain back to the root object, whether directly or indirectly.
>
> Not only are they close, aren't they basically *the exact same code*
> structurally? Meaning apart from the class-specific stuff that would be
> needed (different name of designated initializer, additional parameters,
> etc., etc.), the framework here is exactly the same as it was for the
> subclass (MyClass). I would *expect* it to be the same seeing that it's
> keeping the init chaining intact. Am I missing something or am I
> 'getting it'?
You're getting it. Sorry if I seemed like I was beating you over the
head with it - I caught a case of "If I actually THINK about how to tie
my shoelaces instead of just letting my fingers take care of tying them
for me "automagically", I'll do nothing but tie 'em in knots" syndrome,
and the reply is partly me "untying" the knots I got myself into! When I
got done, I decided it was worth going ahead and posting anyway in case
somebody else might stumble on it and find it useful, tweaked a couple
of typos, and hit send.
>
> >
> >> c) At each step down the hierarchy through sub-classes, the 'plain' init
> >> would have to be overridden and it would have to return the current
> >> class' designated initializer, correct? In other words, you'd have to
> >> re-write init for each sub-class where there is a new designated
> >> initializer.
Quickie comment here as I see some confusion in your reply to Pascal -
When the plain init method is called, the caller doesn't get the current
class' designated initializer - it gets THE RESULT OF CALLING the
current class' designated initializer - an initialized and ready-to-use
instance of a subclass that inherits from the current class.
> >
> > Basically, yes. See the snippets above.
>
> Yep, my above two comments discusses this.
>
> thanks for your response.
> -jonR
--
Security provided by Mssrs Smith and/or Wesson. Brought to you by the letter Q
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | comp.lang.objective-c
csiph-web