The Old Way: Forward Declarations
Older languages like C (and recently, Objective-C), won’t just let you call a function or method whose definition is later on in the same file. Consider these two C functions, which appear in my Inpulse Magic 8-Ball tutorial:
void set_time_mode() { start_timer(TIME_UPDATE_INTERVAL_LENGTH_MS, &update_time_display); } void update_time_display() { pulse_blank_canvas(); pulse_get_time_date(¤t_time); printf("The time is\n%d:%0.2d:%0.2d\n", current_time.tm_hour, current_time.tm_min, current_time.tm_sec); set_time_mode(); }
The function set_time_mode
refers to update_time_display
, whose definition comes after set_time_mode
‘s. As far as the C compiler is concered, set_time_mode
doesn’t exist yet, and it will refuse to compile, giving you an error message that looks something like this:
src/pulse_app.c: In function ‘set_time_mode’: src/pulse_app.c:76: error: ‘update_time_display’ undeclared (first use in this function) src/pulse_app.c:76: error: (Each undeclared identifier is reported only once src/pulse_app.c:76: error: for each function it appears in.)
You can’t simply switch the order of the two functions since update_time_display
also calls set_time_mode
.
Forward declarations solve this problem. By including the signature for update_time_display
before the definition of set_time_mode
, we give the compiler enough information so that it knows what to do with update_time_display
when it’s compiling set_time_mode
:
void update_time_display(); void set_time_mode() { start_timer(TIME_UPDATE_INTERVAL_LENGTH_MS, &update_time_display); } void update_time_display() { pulse_blank_canvas(); pulse_get_time_date(&current_time); printf("The time is\n%d:%0.2d:%0.2d\n", current_time.tm_hour, current_time.tm_min, current_time.tm_sec); set_time_mode(); }
The code above compiles.
The New Way: No Forward Declarations
Newer languages like Python and Ruby don’t need forward declarations. You can have a method refer to another method that appears later in the file in Python:
# A quick and dirty example in Python def first_method(): # second_method appears later in this module second_method("Hello there") def second_method(statement): print statement first_method()
And here’s the Ruby equivalent:
# A quick and dirty example in Ruby def first_method # second_method appears later in this module second_method "Hello there" end def second_method(statement) puts statement end first_method
Objective-C joins the club in Xcode 4.3 and later (as of this writing, the current version of Xcode is 4.5); you no longer need to make forward declarations. The compiler will “look ahead” if the function or method it’s compiling makes calls to functions or methods that appear later on in the file.
This means that the following code compiles in Xcode (at least in Objective-C):
void set_time_mode() { start_timer(TIME_UPDATE_INTERVAL_LENGTH_MS, &update_time_display); } void update_time_display() { pulse_blank_canvas(); pulse_get_time_date(&current_time); printf("The time is\n%d:%0.2d:%0.2d\n", current_time.tm_hour, current_time.tm_min, current_time.tm_sec); set_time_mode(); }
3 replies on “A Step Forward (or: Objective-C Doesn’t Need Forward Declarations Anymore)”
Call me old school, but I think these declarations are good coding practices. Maybe a bit cumbersome, but ensures some degree of discipline in your code design.
Matt: I’m all for languages that help enforce better programming practices, but I don’t think forward declarations do that. I’m pretty sure that they’re a vestige from the days when processor power and RAM were considerably more precious and the programmer was called upon to ease the burden on the compiler more often.
Keep in mind that when I started getting into iOS and Objective-C, I looked at .h files and went “I thought I was done with those!”
[…] A Step Forward (or: Objective-C Doesn’t Need Forward Declarations Anymore) (Global Nerdy) […]