Clash-happy method names

This post lists a few special-case method names that are somewhat likely to be used accidentally by you but can only be used correctly if you understand their built-in functions.  Specifically: class, description, load, and hash.

Why it’s tricky, by example

Here’s an easy way to mess this up: start with a model object meant to match a table of a database on your server.  Maybe you started by defining your fields.  You’re making a table to represent player characters, so they have properties like alignment, level, race, or class.  Sounds fine, right?  Next you mirror these types in your iOS code, with just a bunch of instance variables with the same names.  Instance variable names won’t class with method names, so you’re still ok.  And then down the road you want to turn these things into properties.  So you mindlessly turn everything into a property and BAM your code suddenly starts acting extremely weird, and you have no idea why.

It’s because you implicitly have defined a method called “class” when you declared all your instance variables as property, and you copied all those from your server’s table fields.  Now you have a choice:

1. Make your code uglier by avoiding properties, or

2. Make your code uglier by dropping consistency, and do some special-case handling for the “class” field.

Of course, the real solution is

3. Don’t use clash-friendly names anywhere in your pipeline, even across platforms.

Hence the usefulness of this post (there are other cases too).  Some people might argue in favor of

4? Change every single instance variable everywhere to start (or end) with an underscore to avoid name clashes,

but I think it is confusing to even allow names that are off-by-an-underscore, and that it is more a work-around than a good general approach.  But that is also a prevalent and valid perspective.

In any case, it’s good to know about these few special-case methods:

class

This method is meant to return the

Class

object for the class of the receiver. You never need to write it, and overriding it is probably not your best move. It can be used for things like deciding what methods your object can respond to, and confusion about that can lead to horrible burning crashes with blood, disembodied limbs, and gory stack traces flying willy-nilly about the room.

description

Beginners often think (at least I did) that %@, as a string formatter, means “print out an NSString.” But that’s not true – it really means, “print out an object,” and an object can be anything, including an NSString (so if you previously thought it was for NSString’s, your thought is true – it’s just that you can print out so much more than you ever dreamed). Of course, there is the big question of how do you convert any object to a string? And the answer is that every object has a

description

method which is meant to return a string representing that object. If you override this method, anyone printing your object (which could easily happen indirectly by, say, printing out the contents of an NSArray) will invoke your description call — if you provide some other type of

description

method, you will end up scratching your head at the weird debug output you get.

load

The

load

method is a class method (signature + (void)[MyClass load]). It is designed to give you a chance to run some code at the load-time of a binary, in a way that does not require any specific invocation. For example, you could build an audio library that has to call some one-time global init function like AudioInit(). Instead of having run-once code in your init function that looks like this:

if (didGlobalInit == NO) {
  AudioInit();
  didGlobalInit = YES;
}

You can just do this:

+ (void)load {
  AudioInit();
}

So if you were thinking of have static methods called

load

and

save

meant to be called explicitly by your own code, you need to choose new names.

hash

The hash method is used by collections like dictionaries and sets to do fast lookups (more info  on that here).  If you override it for your own hash purposes, your dictionaries and sets are most likely to (a) simply act like things you added aren’t there during lookups, or (b) possibly crash.

Others?

I’m probably leaving out a few. Please let me know if you’ve collided with other special-case names that you weren’t expecting – I’ll add them to this list.

References

Apple’s docs on:

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*