PDA

View Full Version : Please could someone explain "self" and "super" to me?




glossywhite
Oct 16, 2009, 07:53 AM
Please could someone explain "self" and "super" to me?. There is NOWHERE on the internet that explains this thoroughly, to a newcomer to programming, which I find a little worrying. I get pointers and I know what they do, and I know that "self" & "super" are to do with pointers, but seeing as I am a VERY new Cocoa coder, I would love it if someone could explain, clearly and LOGICALLY, what they mean and what they do.

Thanks :)



whooleytoo
Oct 16, 2009, 08:29 AM
Self refers to the object you're in. Super refers to the superclass (or parent class) of the object you're in.

Self enables you call methods in an object, from other methods in the same object. Or, it enables you to access instance variables/properties of the current object, from methods in that object.

Super is normally used if you've over-ridden an instance method, but now you want the call the original method from the parent class.

Let's say you create a Person class to store a person's details, and that class has a getName method which returns that person's name ("John Smith"). Now let's say you create a subclass of Person called Manager, and you override getName to return "MR. John Smith".

Now, from any other method of Manager, you can do the following:


- (NSString*) outPutName
{
NSString* first = [self getName]; // This will return "MR. John Smith"
NSString* second = [super getName]; // This will return "John Smith"

NSLog(first);
NSLog(second);
}


Hope that helps.

schoeringhumer
Oct 16, 2009, 08:36 AM
if you know a little bit about java ... there is a keyword called "this" ...
hopefully i could help ....

glossywhite
Oct 16, 2009, 09:08 AM
Self refers to the object you're in. Super refers to the superclass (or parent class) of the object you're in.

Self enables you call methods in an object, from other methods in the same object. Or, it enables you to access instance variables/properties of the current object, from methods in that object.

Super is normally used if you've over-ridden an instance method, but now you want the call the original method from the parent class.

Let's say you create a Person class to store a person's details, and that class has a getName method which returns that person's name ("John Smith"). Now let's say you create a subclass of Person called Manager, and you override getName to return "MR. John Smith".

Now, from any other method of Manager, you can do the following:


- (NSString*) outPutName
{
NSString* first = [self getName]; // This will return "MR. John Smith"
NSString* second = [super getName]; // This will return "John Smith"

NSLog(first);
NSLog(second);
}


Hope that helps.

The first part makes perfect sense, but the code doesn't, as it is related to other code which you have missed out, and I'm finding it hard to mentally relate your code to another part of the code which doesn't exist.

notjustjay
Oct 16, 2009, 09:32 AM
Super is normally used if you've over-ridden an instance method, but now you want the call the original method from the parent class.

One useful application of this is when you have a method in the original class that does A, B, and C, and then in the child class you still need it to do A, B, and C, as well as new, child class specific things D and E.

You could copy/paste the code and write a child method that does A, B, and C, D and E. But that's code duplication -- and sometimes you might not even have the original code. So the better thing to do is have the child method call the parent method using super, and then write out just the new code to do D and E. E.g. "Do everything my parent method did, and do all this new stuff."

Or, as some posters have indicated below, the other way around: "Do all this stuff first, and then do the stuff the parent method did" (such as clean up).

lee1210
Oct 16, 2009, 09:41 AM
The first part makes perfect sense, but the code doesn't, as it is related to other code which you have missed out, and I'm finding it hard to mentally relate your code to another part of the code which doesn't exist.

The thing is, you may not have the other code. If you are inheriting from a class for which you only have headers and a binary framework, you just have to go by the header and/or class documentation.

Basically, in this case whooleytoo explained that you have a Person class(which you may have no control over, and no access to the source code), which has a method -(NSString *)getName. Your new Manager class inherits from the Person class. In your Manager class you may need to run the Person version of getName, even though you've overridden it in Manager with your own version of getName. In order to class the Person version of getName, you have to call it on super. Think of super as the same instance, but of the parent class's type.

-Lee

whooleytoo
Oct 16, 2009, 09:46 AM
I don't have Xcode handy to write it out fully & test, so I'll just try and make it a bit clearer.

You're making a subclass of "Person", called "Manager". Both have a method called getName which will return different strings. So, by using self or super, you can Person's getName method, or Manager's getName method; depending on which functionality you want.


// Person.m (Your parent class).
- (NSString*) getName
{
return _name;
}

// Manager.m (Your subclass of Person)
- (NSString*) getName
{
return [NSString stringWithFormat: @"MR. %@", _name];
}

- (NSString*) outputName
{
_name = @"John Smith";

// This will call Manager's getName
NSString* managerName = [self getName]; // "MR. John Smith"

// Whereas this will call Person's getName
NSString* personName = [super getName]; // "John Smith"
}


As I said, super is usually used when you want to call the parent class's method. One good example is "dealloc", the destructor for cleaning up after your object when it's being destroyed. This nearly always has the same format: clean up any instance variables for this class, then call [super dealloc] to clean up any instance variables inherited from the parent class.

E.g.

// In Manager.m
- (void) dealloc
{
// First, release any instance variables specific to Manager class
[_managerRecord release];
[_managerPerformance release];
[_managerReview release];

// Then, you release all instance variables inherited from Person class
// Person.m already has a dealloc destructor, so call this
[super dealloc]; // Calls dealloc from Person.m
}

glossywhite
Oct 16, 2009, 10:27 AM
Is this what happens?

whooleytoo
Oct 16, 2009, 10:59 AM
Is this what happens?

Precisely! As a developer, I inherently lack even the artistic skill to draw that! :p

Self is relatively easy to understand; since all instance method calls take the form [objectname methodname], then it's clear you need the self keyword in order to call methods in the same object.

Super is a bit less clear; but it's often necessary. Particularly (as mentioned by another poster above) if you override a method in order to add to the functionality of the parent's method, not replace it entirely.

So in your method you add the code specific your subclass, then (using super) call the inherited method to execute the generic code for the parent class. The dealloc example above is a very common example of this.

gnasher729
Oct 16, 2009, 11:32 AM
Is this what happens?

Can't quite figure out what that drawing means.

"self" is quite easy to explain: Whenever you send a message, you need someone to send it to. Either an object, if you are sending an instance method, or a class, if you are sending a class method. Inside an instance method, "self" is the object that you sent the message to. Basically, every single instance method has an additional parameter named "self" which is the object that the method was sent to, and because every single instance has that parameter, it isn't worth mentioning in the parameter list.

"super" works very differently: It has to do with what actual code should be executed. A method can be overwritten in a derived class; and overwritten again in the next derived class and so on and so on. Sending a method to "self" will find the actual type of that object, and find the version of the method appropriate for that type, and execute it. Sending the same method to "super" will instead find the implementation in the superclass of the currently running method and execute it; but the message is still sent to the same object.

Example: You have a class Person, a subclass Manager, and a subclass Boss. You are writing an instance method A for class "Manager". The "self" object passed to that method could be a Manager object or a Boss object; it cannot be a Person object. If your method A calls another method B by writing [self B];, then the code that is executed is the Manager version of B if self was a Manager object, and it is the Boss version of B if self was a Boss object. If your method calls [super B], the "Person" version of B will be called, no matter whether self was a Manager or a Boss. If B calls another method [self C]; and the original "self" was a Boss, then that call will execute the "Boss" version of the method.

wlh99
Oct 16, 2009, 01:45 PM
Is this what happens?

Sort of. "self" is refers to a specific instance of the subclass, not the subclass. There is a difference, as there are both class methods and instance methods.

This question touches on exactly what object oriented programming is, and that needs to be understood in order for this to really make sense.

A class is a blueprint, or a factory for an object, say a car (since we don't often build people in real life) It describes what the object is and can do. We ussually never see the code for the class, unless we write it ourselves. Instead we read the Apple docs.

A subclass would be a blueprint on how to build an object that is similar, or an extension of the super class. Lets say, a Corvette. Perhaps we did write the code for the subclass and Apple wrote the code for the car. This is true of nearly every class you write, which will inherit from NSObject at least, and maybe something else.

Now we build a Corvette. we use the init method. Init is a class method that the corvette factory knows how to do. Most likely, the corvette init method first calls the super init to build a basic car, then does it's own thing to customize it to make it a corvette.

now you have a corvette called my myCar. You could send it a message:
[myCar start];

or

[myCar rollUpWindows];

Lets say that the corvette has a feature that the windows roll up by themselves if the speed exceeds 65mph. Somewhere in the class implementation for the corvette there is code to check how fast the car is going, and if it is faster then 65:

[self rollUpWindows];

Get it? You have a corvette, and it is performing an action on itself. At the time the code is writen, it is in the class implementation. There are no corvettes, only the blueprints. So you can't say [myCar rollUpWindows]. My car hasn't been built yet. But, every corvette regardless of name will know how to roll it's own windows up. And the owner of the car doesn't send the message, the car sends the message to itself.

That might make sense now, but not really help you with your specific example and why you asked the question. That is also part of the OOP "idea".

Data encapsulation is the OOP idea that all data is encapsulated in an object. As a programer there is a layer of abstraction from it. Programs aren't cars and people, they deal with data, numbers, etc.

Say you have a document class. This class encasulates the data your program works with. That class has an array of records. Records themselves are objects that know how to do things. Maybe they update themselves with random numbers every hour, or maybe they change color. Abstraction prevents you from knowing or caring about all of that. All you know is that you work with the document.

You create an instance of the document class and are doing things with it. You could
[myDocument addRecord];
[myDocument print];

The addRecord method in the myDocument instance of the document class does it's thing to add the record to the data it stores, then while still in the addRecord method:

[self sortAllRecords];

I hope that makes sense. It's a quick summary of a broad topic that often lasts a couple semesters of study.

firewood
Oct 17, 2009, 09:46 PM
You can have a whole bunch objects of similar type within one "class". The class can also have a bunch of messages (or "methods") that can be sent to any object within that class.

How does the code executing a message in this class know to which object the message was sent?

"self" points to that object within the execution of that message.

A subclass can customize what it does when a message is sent to it, different from what that same message would do an object in the class from which the subclass is derived.

But what if you wanted to do whatever an "un-customized" message would have done in the superclass, inside the executing code for the subclass message?

"super" gives you access to the un-customized messages (or methods).

.no batteries included.