PDA

View Full Version : a little more SELF help.




larswik
Jun 21, 2011, 04:37 PM
I think I almost have an understanding of the 'Self'. From Jim's explanations, Lunda.com video and other resources. There are a few questions I still have.

1) From Main.m, I create an object from a class and alloc and init that object. In this example 'myClass* myObject = [[myClass alloc]init]'

2) When I alloc/init the 'myObject', instance variables are created (if defined) but nothing happens with the methods until a Method is sent a message to do something from Main.m, in this example.

3) Here is what i'm not sure of yet. If myClass has a method definition named -(id)init. Inside of this method I have a line of code, lets say 'score = 10'.
-(id)init{
self = [super init];
score = 10;
return self;
}

So in Main.m, when I say [myClass* myObject] it will then create myObject and while doing so if it sees a method, in the myClass called '-(id)init' the compiler says "ahhh, this means he wants the object, myObject, to be initialized with with the score equal to 10."

Correct me if I am wrong. I send messages to methods to do something. But I don't send a message to a method called-(id)init. Like my new car I got. Ford created that Object and there was a method that was
-(id)init{
self = [super init];
gasGallons = 18;
oilQuarts = 8;
keys = 2;
return self;
}
Now my fordObject already has instance variables initialized when it is created. This then saves me the step of writing code in Main.m like [fordObject gasGallons: 18] and so on. Is this understanding right?

So in the end, I am getting 1 object back to use 'fordObject', with the instance variables already initialized to a value, right? Or, I read, and you guys have mentioned that id is a generic object. when -(id)init method is executed, a second object is created too, fordObject and idObject? In this case idObject would contain the initialized values and not fordObject?

Is id going to be it's own object or is it apart of fordObject?

Thanks again. I think I almost got this.

O' PS. I tried to dumb down my terminology to make it simple. I think it should have been [fordClass *exploreObject] and [fordClass* focusObject] and so on.



chown33
Jun 21, 2011, 05:29 PM
Your post is confused in several places.

First, you've posted some code fragments that can't possibly compile, such as here:
So in Main.m, when I say [myClass* myObject] it will then create myObject
In reality, when you [myClass* myObject] the compiler will fail, because that's not valid syntax.

Please post real code, that has actually been compiled. If you try compiling it and it gets an error, then post the code and the actual error message.

Hypothetical code is much to hard to analyze or debug, because, being hypothetical, it doesn't actually exist. If you want to make actual examples using a Car class you define, and/or a Ford manufacturer of Car instances (again, you define Ford or AutoMfgr or whatever), then make and post actual compilable examples.

Please use Cocoa naming conventions. The biggest one is Class Names Always Start With Upper Case. Always.

If you want to find something out, I suggest writing a program that tells you what happens. Think of it as the Reality Check on your hypothetical.

The obvious one is "What is the value of 'score' after -init?" You should already know how to use NSLog() to print things, so it's a small step to use the expression myObject->score to get the value of the score instance variable belonging to the myObject object.


It may seem crazy or perhaps simple-minded to make these examples, but it's not.

All software consists of modeling things. From numbers modeled as patterns of binary bits (in different representations: floating-point, integer, etc.), to basic arithmetic modeled as transformations of bits, all the way to the complex models of classes and objects and gargantuan databases. It's all models, i.e. abstractions with some things left out, simulated things with only certain properties of interest, etc.

The best way I know of to learn how to make models is to make them and try doing things with them. If they have shortcomings, improve them. If you want to abandon a model entirely, you're free to do that. The worst way to learn how to make models is hypothetically, because you don't have any way to find your errors. The computer is happy to point out your errors, either when the compiler coughs on something you wrote, or when you have a bug that crashes your code. A realized model can be tested. An unrealized model is nothing.

larswik
Jun 21, 2011, 06:47 PM
OK, fair enough, This code works fine for my test.
main
#import <Foundation/Foundation.h>
#import "retriveNumber.h"

int main (int argc, const char * argv[])
{

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

retriveNumber* theNumber = [[retriveNumber alloc]init];
NSLog(@"The num1 is: %i ",[theNumber num]);
NSLog(@"The num2 is: %i ",[theNumber num2]);

[theNumber setNumberToAValue];
NSLog(@"The return after I sent a message to the method: %i ",[theNumber num2]);

[theNumber release];
[pool drain];
return 0;
}


header
#import <Foundation/Foundation.h>

@interface retriveNumber : NSObject {

int num, num2;

}
-(int)num;
-(int)num2;
-(void)setNumberToAValue;
@end
implementation
#import "retriveNumber.h"

@implementation retriveNumber

-(int)num{
return num;
}
-(int)num2{
return num2;
}
-(void)setNumberToAValue{
num2 = 5;
}
-(id)init{
self = [super init];
num = 10;
return self;
}
@end

This does answer my question, kind of. When this line gets executed
retriveNumber* theNumber = [[retriveNumber alloc]init];
I get theNumber Object back and num1 is set to 10 but num2 is not set or defaults to 0 as it's value. I then send a message
[theNumber setNumberToAValue];
which intern sets the num2 instance variable value to 5 and then have it write out to the console.

What I can see is that when an object is created the Methods are ignored unless it sees -(id)init. Which case it executes this method to set up initial values for the object 'theNumber'.

What I don't get is id. What I read is id is a generic object type. -(id)init has a return type of a generic object. I don't see why it is returning a generic object? It seems that when -(id)init method is executed it would just simply give the instance variables initial values for my theNumbers object I am creating in main.

Why does it have to make a generic object to do this?

Thanks.

-Lars

wlh99
Jun 21, 2011, 07:02 PM
I think I almost have an understanding of the 'Self'. From Jim's explanations, Lunda.com video and other resources. There are a few questions I still have.

1) From Main.m, I create an object from a class and alloc and init that object. In this example 'myClass* myObject = [[myClass alloc]init]'

It is important to understand this syntactic shortcut. It is several lines combined into one. You will very often see brackets nested in brackets, and should know how to expand them.

myClass *myObject;
myObject = [myClass alloc];
[myObject init];

Ponder that, and it may answer your next questions. Consider how the order of operations could allow you to combine all that into one line.



2) When I alloc/init the 'myObject', instance variables are created (if defined) but nothing happens with the methods until a Method is sent a message to do something from Main.m, in this example.


You did send a message "init"


3) Here is what i'm not sure of yet. If myClass has a method definition named -(id)init. Inside of this method I have a line of code, lets say 'score = 10'.
-(id)init{
self = [super init];
score = 10;
return self;
}

So in Main.m, when I say [myClass* myObject] it will then create myObject and while doing so if it sees a method, in the myClass called '-(id)init' the compiler says "ahhh, this means he wants the object, myObject, to be initialized with with the score equal to 10."

Correct me if I am wrong. I send messages to methods to do something. But I don't send a message to a method called-(id)init. Like my new car I got. Ford created that Object and there was a method that was

corrected, above.
Read Apples document on memory management. It might be just a bit early for you to understand some if it, but I think it's better to be exposed to it now, even if you don't fully understand it until later. http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

Pay attention to the parts about convience methods vs. init methods. It's a good source of information on the topics you are asking about. And you will be asking about memory management soon anyway.



-(id)init{
self = [super init];
gasGallons = 18;
oilQuarts = 8;
keys = 2;
return self;
}
Now my fordObject already has instance variables initialized when it is created. This then saves me the step of writing code in Main.m like [fordObject gasGallons: 18] and so on. Is this understanding right?

So in the end, I am getting 1 object back to use 'fordObject', with the instance variables already initialized to a value, right? Or, I read, and you guys have mentioned that id is a generic object. when -(id)init method is executed, a second object is created too, fordObject and idObject? In this case idObject would contain the initialized values and not fordObject?

Is id going to be it's own object or is it apart of fordObject?

Thanks again. I think I almost got this.

O' PS. I tried to dumb down my terminology to make it simple. I think it should have been [fordClass *exploreObject] and [fordClass* focusObject] and so on.


What I don't get is id. What I read is id is a generic object type. -(id)init has a return type of a generic object. I don't see why it is returning a generic object? It seems that when -(id)init method is executed it would just simply give the instance variables initial values for my theNumbers object I am creating in main.

Why does it have to make a generic object to do this?

Thanks.

-Lars

init returns the address of the object that was initalized. Consider this line again:

retriveNumber* theNumber = [[retriveNumber alloc]init];

First memory is allocated by [retrieveNumber alloc]
[retrieveNumber alloc] returns the address of the object, which is uninitialized space.
Next, the init method is sent to the address returned by retriveNumber. Not only is your initalization done, but [super init] calls the init method of the super class, in this case NSObject.
The init method returns the address of the object (self), and that address is assigned to retriveNumber.

larswik
Jun 21, 2011, 07:06 PM
Thank you wlh99...

Your one line "You did send a message "init" switched on the light in my brain. It completely escaped me that that was a message I was sending and I had a method for that! So it is not the compiler seeing this an knowing to execute this line of code by chance, I told it to do that with the init message. That is so easy now to grasp that concept of how that one method gets initialized. I originally thought alloc reserved the space in memory and init just then created the object to be used. I did not realize that it was a message to a method.

That part is clear now... id is not :)

-Lars

We are cross posting. I am reading your other post right now

chown33
Jun 21, 2011, 08:01 PM
That part is clear now... id is not :)

The reason for -init returning id is given in "The Objective-C Programming Language", section name "Allocating and Initializing Objects", subheading "Implementing an Initializer".

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocAllocInit.html

I strongly suggest reading the entire document starting from the beginning. You will probably read some things you already know, but I'd wager you'll read more things you don't know.

You should probably read this, too:
Object-Oriented Programming with Objective-C (http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/OOP_ObjC/)
Again, I strongly suggest reading it in full, from the beginning.

wlh99
Jun 21, 2011, 08:02 PM
Thank you wlh99...


That part is clear now... id is not :)

-Lars

We are cross posting. I am reading your other post right now

You are calling [super init] and returning the address returned by that method. All the way up the tree, you are calling init for the NSObject class. But all you really know is that you will be returning an object. If it were -(NSObject)init then when you assigned the value to your pointer declared as MyClass, they wouldn't match and there would be an error. The type ID gets around that.

That might not be completely the whole story, but it is how I understand it.

jiminaus
Jun 21, 2011, 08:03 PM
That part is clear now... id is not :)


id is not an object, it a type.

Recall void* from C. A void* variable can point to anything.

Now consider int*. An int* variable can only point to an int.

Now consider NSString*. An NSString* variable can only point to an NSString object (or a subclass of NSString).

id, on the other hand, is like void*. An id variable can point to any kind of objective-c object. But unlike void*, it must be an objective-c object, it couldn't point to an integer for example.

larswik
Jun 21, 2011, 10:22 PM
"id is not an object, it's a type." - Ding!

I was under the impression that a second object was being created called self that contained the ivars with it's values. But this is happening 'self = [super init]' and not this 'self = [super alloc]init]. No space in memory is being allocated, So self is pointing to the address being created (it's self) and just telling it's self

...."Hey self, memory is already been allocated. Now when I'm initialized I want these instance variables initialized with values. I know this because in main this line of code 'retriveNumber* theNumber = [[retriveNumber alloc]init];' a message was sent to the method -(id)init to do these things (assign initial values) as I am born into the program as a usable object."

This I get now. I am getting 1 object back and it is clear to me how the self = [super init] is working to do all of this.

chown33 - I will look at the doc's. But this interaction and different version of solving this problem put the pieces together for me. Every time I understood a little more.

Thanks you all for your patience and helping me understand.

-Lars

jiminaus
Jun 21, 2011, 11:28 PM
Imagine main is robot (think C-3PO). Image MyClass is another robot. The main robot says to the MyClass robot "alloc". The MyClass robot builds a third robot and returns it back to you. This third robot isn't powered-up, but it can listen for messages. The main robot then says to this new third robot "init". In response to this, the new third robot powers up by initialising its instance variables. The main robot then slaps a "myObject" label onto this third label. (This sentence is talking very loosely, it's not technically correct.) This is what's happening in the line MyClass* myObject = [[MyClass alloc] init].

There's very little magic in Objective-C at the language level. Memory for an object is allocated only because you sent the alloc message to a class. The object is initialised only because you sent the init message to the nascent object. The compiler, or anything else, isn't being cleaver; it isn't thinking about your code, what you need, what you intend, etc.

larswik
Jun 22, 2011, 12:33 AM
The robot explanation is exactly what I was thinking. I must not have been explaining myself well.

When I was out for a walk I had one more thought on the -(id)init method which I think became clear.

Using this example again MyClass* myObject = [[MyClass alloc] init]. The init message is sent to myClass first. If an 'init' method it is not found it travels up super classes till it finds it like in NSObject. But, if myClass has an init method like -(id)init;, it stops there and sends the message to it. That is the reason for the [super init]. myClass method of -(id)init does not have the code necessary to initialize the object. It's just the code that I want to use to be included when the object gets initialized. So [super init] passes the init message further up the chain to perform the initialization of myObject

Is my thinking right there here?

-Lars
.

jiminaus
Jun 22, 2011, 01:47 AM
The robot explanation is exactly what I was thinking. I must not have been explaining myself well.

When I was out for a walk I had one more thought on the -(id)init method which I think became clear.

Using this example again MyClass* myObject = [[MyClass alloc] init]. The init message is sent to myClass first. If an 'init' method it is not found it travels up super classes till it finds it like in NSObject. But, if myClass has an init method like -(id)init;, it stops there and sends the message to it. That is the reason for the [super init]. myClass method of -(id)init does not have the code necessary to initialize the object. It's just the code that I want to use to be included when the object gets initialized. So [super init] passes the init message further up the chain to perform the initialization of myObject

Is my thinking right there here?

-Lars
.

Bingo!! Well done.

larswik
Jun 22, 2011, 03:21 AM
Cool!!! I finally get the self = [super init]!

That you for all the effort you have invested in me!!!!!!

-Lars

balamw
Jun 22, 2011, 05:33 AM
a message was sent to the method

This is the bit that implies to me that you are still missing something, though you may have finally "got it" in your last reply.

The way I understand it at least is that the messages are sent to the objects (robots), and the messages contains the names of methods (init yourself).

In some ways this is bass-ackwards from procedural programming where parameters are passed to functions, and is part of the unlearning process that would be less of an issue if you started with Objective C.

B

jiminaus
Jun 22, 2011, 07:46 AM
A message is made up of three things: a receiver, a selector and a list of parameters.

The following syntax:

[anObject doThingWithString:string1
anotherString:string2];


Is compiled into:

objc_msgSend(
anObject,
@selector(doThingWithString:anotherString:),
string1,
string2
);


objc_msgSend is a function in the Objective-C runtime. It does the work of going up the inheritance hierarchy of the receiver's class to find a method that matches the selector.

The syntax [super blah blah] compiles into a call to obj_msgSendSuper, which does the same but starts the method search with the receiver's superclass.


This is all described in the Messaging chapter of the Objective-C Runtime Programming Guide.