Pass-by-reference and pass-by-value are pretty confusing when you start learning to code. When I first saw them, I know I ignored the distinction (until I got tired of my code not doing what I expected). Throwing collections into the mix just makes it worse.

Today, though, we stumbled on a pretty decent analogy for passing-by-reference: a reference to an object is like a leash to a dog. Let’s take our dog Dagwood for a walk.

1 Dog dagwood = new Dog("Dagwood");

new Dog() creates, of course, a new Dog object. Dog dagwood creates a reference that can point to any Dog object – it’s really the leash, but we name our references for what they point to, rather than what they are: a reference, a handle, a leash. The equals sign takes the leash, and hooks it to Dagwood’s collar. Now we can take Dagwood for a walk.

1 dagwood.walk();

To tell Dagwood it’s time to walk, we tug on the leash. He feels the tug, and gets the message, so he starts following us. We come to a busy road, and wait for the crossing signal, but Dagwood’s oblivious, and tries to cross anyway.

1 dagwood.halt();

Since we’re stopped, he feels the tug of the leash again, gets the message, and stops. We’re sending messages to Dagwood through his leash. In OO terms, sending a message to an object means calling one of its methods. We’re calling methods on our Dagwood through our reference to him, through the leash.

Storing a reference in an array

In the park, we find a snack shop. We’re getting hungry, but the snack shop doesn’t let dogs inside. Luckily, there’s a chain link fence, and in our eyes, a chain link fence is nothing but a big row of places for us to attach a dog leash. We tie a spare leash to the end of the fence, and attach it to Dagwood’s collar.

1 Dog[] fence = new Dog[10]; // only room for 10 dogs
2 fence[0] = dagwood;

What’s happening here in OO terms is that our reference to Dagwood, our leash, is copied into the zeroth slot on the fence. It’s not our leash, but it’s one just like it. So now there are two leashes on Dagwood: one in our hand, and one on the fence. We’ll take our leash off Dagwood, since we can’t very well hold it while we’re in the store.

1 dagwood = null;

Don’t worry, he’s fine…he’s still tied to the fence, by that other leash. Let’s go buy cashews.

When we come out of the store, we want to re-attach our leash to Dagwood.

1 dagwood = fence[0];

Now let’s untie him from the fence, and head over to the lake.

1 fence[0] = null;

Passing by reference

Passing references to methods works in much the same way. Dagwood got kind of stinky, swimming in the lake, so let’s bring him to the groomer for a bath.

1 DogGroomer.shampoo(dagwood);

When you pass a reference to a method, your reference is copied into that method. Again, it’s like a new leash, one just like ours, springs into the groomer’s hand – now Dagwood’s attached to us, and the groomer. He gets fidgety when he’s getting bathed, so it’s just as well.

From the groomer’s perspective, it might look like this:

1 void shampoo(Dog doggie) {
2     wet(doggie);
3     apply(shampoo, doggie);
4     rinse(doggie);
5     towelDry(doggie);
6 }

The groomer doesn’t care what Dagwood’s name is, she just keeps calling him “doggie.” That’s ok, she must see a lot of dogs during the day…names aren’t that important to her. The interesting thing is, even though it’s the groomer who’s shampooing our dog, since we still have a leash on him, we can observe him getting cleaner.

When she’s done, the procedure ends, the method returns, and her leash to Dagwood disappears. Which is fine, because he’s stopped fidgeting, now that he’s dry.

Garbage collection

We head back home through the park. Dagwood’s itching to run around, but we’re tired, so we just unleash him. Hopefully we can find him before it gets dark…

1 dagwood = null;

Unfortunately, the dog catcher spots him running around without a leash, which is illegal in these parts – a stray dog will hang around forever, eating up resources. The dog catcher carries off our poor Dagwood, and destroys him. We take it in stride, and try to keep the whole circle of life allocation-deallocation in mind.

So…

So that’s how references work. It’s why code like this (C#) will ensure the balloon bouquet has at least one balloon that says “Happy Birthday!”:

1 List<Balloon> balloons = GetBalloons();
2 Balloon printed = balloons.Find(Balloon.IsPrinted);
3 if (printed == null) {
4    printed = new Balloon();
5    printed.PrintMessage("Happy Birthday!");
6    balloons.Add(printed);
7 }
8 return balloons;