TweetFollow Us on Twitter

Jun 97 - Getting Started

Volume Number: 13 (1997)
Issue Number: 6
Column Tag: Getting Started

Filling in Some of the Objective-C Pieces

by Dave Mark

Last month, we learned most of the syntax of the Objective-C language. Since then, I have been scorching the e-mail, newsgroups, and phone lines trying to learn more. Much thanks to Michael Rutman, David Klingler, Bob McBeth, and Eric Gundrum for their time and energies in trying to get me on the straight and narrow. As always, the good stuff is theirs, the mistakes, mine.

@private, @public, and @protected

For me, much of the Objective-C learning process involves learning the differences between C++ and Objective-C. For example, C++ allows you to use the access specifiers public:, private:, and protected: to define the scope of a classes' data members and member functions. Objective-C offers a similar mechanism you can use to specify the scope of a classes' instance variables (methods are always public): the compiler directives @private, @public, and @protected.

Here's the official description of each of these compiler directives:

@private
the instance variable is accessible only within the class that declares it.
@protected
The instance variable is accessible within the class that declares it and within classes that inherit it.
@public
The instance variable is accessible everywhere.

Instance variables default to @protected, which makes sense. After all, if you mark an instance variable as @public, that would defeat the whole point of data encapsulation. The point is, you want to force access to your instance variables to occur via one of your classes' methods. So just forget about the @public compiler directive. The default setting of @protected will serve you in the vast majority of cases.

The @private directive does have its place, though. You would use @private if you don't want the instance variable inherited by subclasses. Perhaps you don't want a subclass monkeying with a variable that is key to the architecture of the base class. Or perhaps you want to minimize the dependencies between the base and sub classes. Though @private does have its place, don't use it unless you absolutely have a reason to. The general opinion seems to hold that you should never use @private at all -- that all classes should have all functionality overridable. Just wanted to make sure you heard both sides...

Here's an example that uses all three directives:

@interface Employee : Object
{
	char		*name;

@private
	int		yearsWithCompany;
	int		hoursVacation;

@protected
	char		*title;

@public
	id			supervisor;
	id			officeMate;
}

The @public, @private, and @protected compiler directives hold true for all instance variables that follow until either the end of the class or another directive is encountered. In the example above, the name variable is @protected, since it is not marked otherwise. yearsWithCompany and hoursVacation are @private, title is protected, and supervisor and officeMate are public. Of course, this sample was just to show you how this works and is not intended as realistic code.

Bottom line, your best bet is to leave these directives out of your code and just use the default setting of @protected. On the other hand, it is worth knowing how this works so you can read sample code that uses it and so you can use @private if you find a case where it makes sense.

Init vs. Init:

In last month's column, we looked at a sample program that included a simple class named Number. Here's the Number implementation:

#import "Number.h"

@implementation Number 

- init:(int)startValue /* This is BAD FORM - see below */
{
 [super init];

 value = startValue;

 return self;
}

- squareSelf
{
 value *= value;

 return self;
}

- print
{
 printf( "Number value: %d\n", value );

 return self;
}

@end

The Number class includes a method named init: which takes a single parameter. As it turns out, calling an initialization method init when it takes a parameter is a bad thing. The name init should be reserved for initialization methods with no parameters. Imagine if you had two different classes, each of which declared an init: method, one of which took a float, and one of which took an int as a parameter. Now imagine you had two object pointers, each declared as an id, one pointing to an object of one class, the second pointing to an object of the second class. If you send an init: method to one of these objects, the fact that both init: methods have the same name and yet take different parameter types will cause confusion and potential bad behavior. The name of your initialization method is what sets it apart from others. You'll see examples of this throughout the remainder of this column.

In the simplest case, an initialization method with no parameters, you'll definitely want to use the name init. The name init implies no parameters. The parameterless init starts off by sending the init method to its superclass, then initializing any instance variables that don't depend on parameters, and finally returning self.

Here's an example:

- init
{
	[super init];

	blockSize = 512;

	return self;
}

In this hypothetical example, blockSize is an instance variable whose initial value does not depend on a parameter. (In real life, we'd likely use a #define or, in C++ a const, but bear with the example.) Note that we sent the init message to our superclass before we do anything else. It is important that you send the initialization message to your superclass before you mess with your instance variables or call any of your other methods. Reason being, when you call your superclasses' initialization method, you give your superclass a chance to initialize its variables and a chance to initialize its superclass, etc.

If your class requires an initialization method that takes a parameter, give it a name that starts with init, then add text that reflects the parameters. For example, suppose you had a sequence of classes, Shape, Circle, and Cylinder, where Circle was derived from Shape, and Cylinder derived from Circle. Asssuming it took no parameters, the Shape initialization method would be called init. The Circle initialization method would require a radius, and might be called initRadius:, and the Cylinder's initialization method might be called initRadius:height:. You get the idea.

A Multi-Class Example

Designing your initialization methods can get a little more complex when you are working with subclasses. In the example above, the Shape class has an init method, while the Circle class, derived from Shape, adds a radius parameter in a method named initRadius:. So far, no problem. To initialize its superclass, initRadius: just sends an init message to its superclass:

[super init]

But what about the initRadius:height: method of the Cylinder class? Should it send an init message to its superclass? That doesn't make sense, since its superclasses' initialization method is initRadius: and takes a parameter. The correct approach is for each class to include all initialization methods of its superclass, adding in any additional methods for extra/differing parameters that it brings to the table. In our example, Shape would feature an init method, Circle would feature init and initRadius: methods, and Cylinder would feature init, initRadius:, and initRadius:height: methods.

Each init method will send an init message to its superclass, and set any instance variables unique to its class to a default value. For example, the Circle init method would set radius to 0 (or whatever) and the Cylinder init method would set height to 0.

Additional methods that are overriding existing super class methods send an initialization message to the superclass, passing parameters as appropriate. For example, the Cylinder initRadius: method sends an initRadius: message to Circle.

Finally, methods that don't have a matching method in the superclass send an initialization message to self using the method that most closely matches itself. For example, the Circle classes' initRadius: method sends an init message to self (no parameters), while the Cylinder classes' initRadius:height: method sends an initRadius: message to itself but includes the radius parameter. Once the called initialization method returns, the calling method continues by setting its unique instance variables to the parameter passed in to it. For example, once initRadius:height: calls [self initRadius:r] (which will set the radius instance variable to r), it then sets the height instance variable to h (the passed in height parameter).

If the last few paragraphs have left you a bit dazed and confused, not to worry. Here's a program that brings this all to life. As you go through the code, try to follow the chain of initialization. Where does each instance variable get initialized? Can you predict the sequence of initializations when initRadius:height: gets called? Try to work this out before you get to the project run at the end of the column.

The source code that follows is a ".m" and ".h" file for each of the three classes Shape, Circle, and Cylinder. In addition, you'll see a listing for main.m, the main() function that starts the ball rolling.

Shape.m

#import "Shape.h"

@implementation Shape

- init
{
 [super init];

 printf( "\n[Shape init]\n" );

 return self;
}

@end

Shape.h

#import <Object.h>

@interface Shape : Object
{
}

- init;

@end

Circle.m

#import "Circle.h"

@implementation Circle

- init
{
 [super init];

 printf( "[Circle init] - Set radius to 0...\n" );

 radius = 0;

 return self;
}

- initRadius:(int)r
{
 [self init];
 radius = r;

 printf( "[Circle initRadius] - Set radius to %d...\n",
									r );

 return self;
}

@end

Circle.h

#import "Shape.h"

@interface Circle : Shape
{
 int radius;
}

- init;
- initRadius:(int)r;

@end

Cylinder.m

#import "Cylinder.h"

@implementation Cylinder


- init
{
 [super init];

 printf( "[Cylinder init] - Set height to 0...\n" );

 height = 0;

 return self;
}

- initRadius:(int)r
{
 [super initRadius:r];

 printf( "[Cylinder initRadius]\n" );

 return self;
}

- initRadius:(int)r height:(int)h
{
 [self initRadius:r];

 height = h;

 printf
 ( "[Cylinder initRadius:height:] - Set height to %d...\n", h );

 return self;
}

@end

Cylinder.h

#import "Circle.h"

@interface Cylinder : Circle
{
 int height;
}

- init;
- initRadius:(int)r;
- initRadius:(int)r height:(int)h;

@end

main.m

#include "Cylinder.h"

void main()
{
 id shape = [[Shape alloc] init];
 id circle = [[Circle alloc] initRadius:33];
 id cylinder = [[Cylinder alloc] initRadius:27 height:10];

 [shape free];
 [circle free];
 [cylinder free];
}

Running the Program

When you run the program above, here's what you see:

[Shape init]

[Shape init]
[Circle init] - Set radius to 0...
[Circle initRadius] - Set radius to 33...

[Shape init]
[Circle init] - Set radius to 0...
[Cylinder init] - Set height to 0...
[Circle initRadius] - Set radius to 27...
[Cylinder initRadius]
[Cylinder initRadius:height:] - Set height to 10...

As you can see, the listing is broken into three parts, each produced by the initialization of a Shape, Circle, and Cylinder, respectively. Note that when (inside main.m) we created a Shape and sent it an init message, this produced a call of the Shape classes' init method. Simple. Of course, we really should have left the init method out of the Shape class, since it doesn't do anything but add overhead. If we left it out, the right thing would have happened (the init message would have found its way to the Object class).

When we created a Circle and sent it the initRadius: message, we spawn a chain of init messages to Shape and then Circle. Finally, the initRadius: message gets sent to Circle.

The Cylinder object produces a similar chain of initialization. First, we see the chain of init messages from Shape to Circle to Cylinder, then the chain of initRadius: messages from Circle to Cylinder, followed finally by the initRadius:height: message to Cylinder.

Till Next Month...

Spend some time looking over this output till you get the pattern. Once you understand this initialization technique, think about what would happen if you added an Oval class as a subclass to Circle, with an added width instance variable. How would this affect the initialization chain? If you have access to an Objective-C environment, take the time to enter this code and take it for a spin. Add some methods of your own (an area method for Circle, perhaps?) and experiment! See you next month...

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Logic Pro X 10.1.1 - Music creation and...
Apple Logic Pro X is the most advanced version of Logic ever. Sophisticated new tools for professional songwriting, editing, and mixing are built around a modern interface that's designed to get... Read more
VLC Media Player 2.2.0 - Popular multime...
VLC Media Player is a highly portable multimedia player for various audio and video formats (MPEG-1, MPEG-2, MPEG-4, DivX, MP3, OGG, ...) as well as DVDs, VCDs, and various streaming protocols. It... Read more
Sound Studio 4.7.8 - Robust audio record...
Sound Studio lets you easily record and professionally edit audio on your Mac. Easily rip vinyls and digitize cassette tapes, or record lectures and voice memos. Prepare for live shows with live... Read more
LibreOffice 4.4.1.2 - Free, open-source...
LibreOffice is an office suite (word processor, spreadsheet, presentations, drawing tool) compatible with other major office suites. The Document Foundation is coordinating development and... Read more
Freeway Pro 7.0.3 - Drag-and-drop Web de...
Freeway Pro lets you build websites with speed and precision... without writing a line of code! With its user-oriented drag-and-drop interface, Freeway Pro helps you piece together the website of... Read more
Cloud 3.3.0 - File sharing from your men...
Cloud is simple file sharing for the Mac. Drag a file from your Mac to the CloudApp icon in the menubar and we take care of the rest. A link to the file will automatically be copied to your clipboard... Read more
Cyberduck 4.6.5 - FTP and SFTP browser....
Cyberduck is a robust FTP/FTP-TLS/SFTP browser for the Mac whose lack of visual clutter and cleverly intuitive features make it easy to use. Support for external editors and system technologies such... Read more
Firefox 36.0 - Fast, safe Web browser. (...
Firefox for Mac offers a fast, safe Web browsing experience. Browse quickly, securely, and effortlessly. With its industry-leading features, Firefox is the choice of Web development professionals and... Read more
Thunderbird 31.5.0 - Email client from M...
As of July 2012, Thunderbird has transitioned to a new governance model, with new features being developed by the broader free software and open source community, and security fixes and improvements... Read more
VOX 2.4 - Music player that supports man...
VoxIt just sounds better! The beauty is in its simplicity, yet behind the minimal exterior lies a powerful music player with a ton of features & support for all audio formats you should ever need... Read more

Get The Whole Story – Lone Wolf Complete...
Get The Whole Story – Lone Wolf Complete is Now Available and On Sale Posted by Jessica Fisher on February 27th, 2015 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Who Wore it Best? The Counting Dead vs....
Like it or not, the “clicker” genre, popularized by cute distractions like Candy Box and Cookie Clicker, seems like it’s here to stay. So Who Wore it Best? takes a look at two recent examples: The Counting Dead and AdVenture Capitalist. | Read more »
Card Crawl, the Mini Deck Building Game,...
Card Crawl, the Mini Deck Building Game, is Coming Soon Posted by Jessica Fisher on February 27th, 2015 [ permalink ] Tinytouchtales and Mexer have announced their new game, | Read more »
Witness an all new puzzle mechanic in Bl...
Well, BlastBall MAX is not one of those games and is bucking trends such as timers, elements of randomness, and tacked-on mechanics in favor of pure puzzle gameplay. When you first boot up the game you’ll see a grid made up of squares that are each... | Read more »
This Princess Has a Dragon and She isn’t...
This Princess Has a Dragon and She isn’t Afraid to Useit. | Read more »
Mecha Showdown Review
Mecha Showdown Review By Lee Hamlet on February 27th, 2015 Our Rating: :: IN A SPINUniversal App - Designed for iPhone and iPad Mecha Showdown replaces traditional buttons with a slot machine mechanic in this robot fighting game,... | Read more »
Reliance Games and Dreamworks Unveil Rea...
Reliance Games and Dreamworks Unveil Real Steel Champions Posted by Ellis Spice on February 27th, 2015 [ permalink ] Reliance Games and Dreamworks have announced that a third game in | Read more »
Sum Idea Review
Sum Idea Review By Jennifer Allen on February 27th, 2015 Our Rating: :: TAXING NUMBERSUniversal App - Designed for iPhone and iPad Sum Idea is a fairly charming but taxing puzzle game.   | Read more »
A New Badland Update Brings Daydream Lev...
A New Badland Update Brings Daydream Levels to Co-Op Posted by Ellis Spice on February 27th, 2015 [ permalink ] Universal App - Designed for iPhone and iPad | Read more »
Slashing Demons Review
Slashing Demons Review By Lee Hamlet on February 27th, 2015 Our Rating: :: IT'S A LONG WAY TO THE TOPUniversal App - Designed for iPhone and iPad Slashing Demons lacks the depth or scope to take it beyond the point of being just... | Read more »

Price Scanner via MacPrices.net

Apple CEO Tim Cook to Deliver 2015 George Was...
Apple CEO Tim Cook will deliver the George Washington University’s Commencement address to GWU grads on May 17, at which time he will also be awarded an honorary doctorate of public service from the... Read more
Apple restocks refurbished Mac minis for up t...
The Apple Store has restocked Apple Certified Refurbished 2014 Mac minis, with models available starting at $419. Apple’s one-year warranty is included with each mini, and shipping is free: - 1.4GHz... Read more
Save up to $50 on iPad Air 2s, NY tax only, f...
 B&H Photo has iPad Air 2s on sale for $50 off MSRP including free shipping plus NY sales tax only: - 16GB iPad Air 2 WiFi: $469.99 $30 off - 64GB iPad Air 2 WiFi: $549 $50 off - 128GB iPad Air 2... Read more
16GB iPad Air 2 on sale for $447, save $52
Walmart has the 16GB iPad Air 2 WiFi on sale for $446.99 on their online store for a limited time. Choose free shipping or free local store pickup (if available). Sale price for online orders only,... Read more
iMacs on sale for up to $205 off MSRP
B&H Photo has 21″ and 27″ iMacs on sale for up to $205 off MSRP including free shipping plus NY sales tax only: - 21″ 1.4GHz iMac: $1029 $70 off - 21″ 2.7GHz iMac: $1199 $100 off - 21″ 2.9GHz... Read more
Apple Takes 89 Percent Share of Global Smartp...
According to the latest research from Strategy Analytics, global smartphone operating profit reached US$21 billion in Q4 2014. The Android operating system captured a record-low 11 percent global... Read more
New Travel Health App “My Travel Health” iOS...
Rochester, Minnesota based Travel Health and Wellness LLC has announced that its new iOS app help safeguard the user’s health when traveling abroad — “My Travel Health” is now available on the Apple... Read more
Sale! MacBook Airs for up to $115 off MSRP
B&H Photo has MacBook Airs on sale for up to $100 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 11″ 128GB MacBook Air: $799 100 off MSRP - 11″ 256GB MacBook Air: $999 $100... Read more
15-inch 2.0GHz Retina MacBook Pro (refurbishe...
The Apple Store has Apple Certified Refurbished previous-generation 15″ 2.0GHz Retina MacBook Pros available for $1489 including free shipping plus Apple’s standard one-year warranty. Their price is... Read more
Wither The iPad mini? End Of The Road Imminen...
AppleDailyReport’s Dennis Sellers predicts that the iPad mini is going to be left to wither on the vine, as it were, and then just allowed to fade away — a casualty of the IPhone 6 Plus and other... Read more

Jobs Board

Sr. Technical Services Consultant, *Apple*...
**Job Summary** Apple Professional Services (APS) has an opening for a senior technical position that contributes to Apple 's efforts for strategic and transactional Read more
Event Director, *Apple* Retail Marketing -...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global engagement strategy and team. Delivering an overarching brand Read more
*Apple* Pay - Site Reliability Engineer - Ap...
**Job Summary** Imagine what you could do here. At Apple , great ideas have a way of becoming great products, services, and customer experiences very quickly. Bring Read more
*Apple* Solutions Consultant - Retail Sales...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Solutions Consultant - Retail Sales...
**Job Summary** As an Apple Solutions Consultant (ASC) you are the link between our customers and our products. Your role is to drive the Apple business in a retail Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.