Welcome to part three of this series -I hope youʼre enjoying it! Last week we looked at how we separate classes in to separate files (interface and implementation), this week weʼre going to look at classes again, but a little bit more in depth. Weʼll also take a peak at inheritance and how it works, along with variable scope.
So far, we have had some great feedback via email, twitter and comments. Itʼs great to see so many people are interested in this subject and itʼs even better to see that so many of you are trying it out for yourself and asking some great questions. Keep it up!
In Review: Classes & Objects
Letʼs review what we have learned about classes in this series so far. If you donʼt know any of this, feel free to skim back to the last tutorial to re-cap. Ok, so, what are classes?
A class is a collection of encapsulated data and custom methods. A class may hold many different kinds of data, and the class methods usually (but not always) perform action related to that data. In Objective-C, a class is usually composed of two files: an interface file and an implementation file. The interface file uses the .h file extension by convention and is where the person using the class can quickly find the methods and data members available to the class. The implementation file uses the .m file extension by convention and is where the majority of the code resides because it contains the actual implementation of all the functions declared in the interface.
So, what makes a class different from an object? What is an object? An object is an instance of a class. Think back to our example with the car in the last part of the series. Where car is the class, then myCar,dansCar, and yourCar would all be objects because they are instances of the car class.
Classes from Apple (and some history)
Before we carry on, Iʼd like to share a few (of many) common classes youʼll be using a lot that are provided by Apple, but first a quick history lesson.
Many classes Apple provides are prepended by the abbreviation “NS”, which stands for NextStep. When Steve Jobs left Apple, he founded NeXT, creating workstation computers that ran on its operating system. The object orientated programming language used on those machines was called NeXTSTEP, which is where we get the “NS” from. When Apple ʻacquiredʼ (another history lesson in itself) NeXTSTEP, they decided to base Mac OS X on NeXTSTEP.
Here are some simple, common classes weʼll see a lot of:
NSString is a string of text that is immutable.
NSMutableString is a string of text that is mutable.
NSArray is an array of objects that is immutable.
NSMutableArray is an array of objects that is mutable.
NSNumber holds a numeric value.
Weʼll learn many more later on, but for now the above will come in handy. Youʼre probably wondering what mutable and immutable means, which is an entirely reasonable question. If an object is immutable that means when we create the object and assign a value then it is static. The value can not be changed. If an object is mutable then it is dynamic, meaning the value can be changed after creation.
Pointers and Initializing
Letʼs say we want to make a static string of text and log it, how would we go about it? In our code it would look something like this:
testString = @"Here's a test string in testString!";
NSLog(@"testString: %@", testString);
I created this file in XCode by going to File > New Project > Mac OS X > Application > Command Line Tool > Type: Foundation (quite a journey!) and editing the implementation (extension: .m) file in the project.
There are quite a few things here that are new, so letʼs examine the above piece by piece.
First of all, we import the foundation library (this is because we set type to Foundation in the new project window before).
This declares the initial function that will be called when our program begins execution. The two parameters separated by a comma are for passing arguments to our application. For now, donʼt worry about these as we wonʼt be needing them right now.
We now create a pointer to an NSString object called testString. Once the first line of this is finished, no string exists yet, only a pointer to a string that we have not yet created. On the next line, we create the string our pointer points to.
We could have alternatively written the last line like this;
testString = [NSString alloc];
This may seem a little confusing at first. In the first version, we have nested the statements within brackets on the same line, whereas in the second we have separated the statements into two lines. The method init initializes all the instance variables in the class.
testString = @"Here's a test string in testString!";
This line is pretty self explanatory, the reason we prepend the quotes with an @ sign is to tell the compiler that the following text is an NSString.
NSLog(@”testString: %@”, testString);
Here we log some information to console. XCode has a debugger built in that you can find under the Run menu. It is very useful when developing an application to log when events are happening and the values of certain variables – it can help when troubleshooting your application and debugging problems. This method works like printf (remember from the first week?) where we supply a string of text with a replacement character (%@ means an Objective-C object).
Finally we return 0, which we know just tells the operating system that the application ended with no problems.
Remember when we made our NSString earlier, we used the init method? Well NSMutableString, NSArray and in fact, every single NS class, also uses init. Seems a lot of wasted code to put the init method in each class, right? It would be, thatʼs why init is usually only implemented once, in the root class known as NSObject. Because classes inherit from each other, a class that is created as a child of another, parent class will automatically gain access to the parent class methods.
Letʼs take NSMutableString for example. NSMutableString has NSString for a parent (making it a child), meaning it inherits from NSString. Meanwhile. NSString has NSObject as a parent, so it inherits from NSObject.
So for example, NSObject has a method called init, so each subclass has this method implemented – which is called a class method. As a matter of fact, the init method in NSObject doesn’t actually do anything it simply returns self. The reason for this is that methods can be overwritten. So the NSArray class may override the init that it inherits to add functionality to it – such as making sure memory is available or preparing any instance variables it may need.
As demonstrated, this is useful because it means that in addition to inheriting from classes we can also extend classes. When we extend a class, we take an existing class and add additional functionality to what is already available. This means you could create your own version of NSString with additional methods, such as a method to fill the string with random text or perform some sort of character encoding.
At this point, the fundamentals of how classes work should be clear. To test your comprehension, see if you can answer the following questions in your mind:
What is the difference between a class and an object?
Why do we use classes?
Why is inheritance useful?
Since classes are such an important part of Objective-C, itʼs important to really feel comfortable working with them. Last week we started looking at classes and this week we have gone into more depth. Next week, you may be glad to hear, weʼre going to move away from the theoretical side and start working on our own simple class or two to perform simple tasks.
Since we have mainly done theory so far, your homework this week is to surf Appleʼs developer website (you should have done this last week) and look at some of the classes available. If you donʼt know where to start, start with something such as NSString. Youʼll become more comfortable with the details of the parent class, the methods, and so on. This will be important later on when youʼre using classes outside of this series and you want to know what methods they inherit or use.
Weʼll get more practical next week with some class coding. Classes really are central to Objective-C, so itʼs mega important that you come to grips with them and the goal of this series is to really ensure that you do!
As usual, if you have any questions or comments, you can reach me by dropping a comment or email. If youʼd like to get in touch with me personally and get a quick answer, send me a tweet!