Chaining is a common term that has several different meanings. This episode explains how you can use chaining in your programs and how it works.
This episode describes four kinds of chaining:
- Object instance chaining as in a linked list or even from parent to child nodes in a binary tree.
- Method call chaining as when methodA calls methodB which then calls methodC.
- Class inheritance chaining which results in a parent-child relationship among your class hierarchy.
- And finally operator chaining when you have multiple operators in a compound statement.
The last type of chaining was the chaining that I had in mind when I started preparing this episode. But then I added the other chaining types too. They seem to fit well and should give you some extra relationships in your own mind to help relate programming topics. Listen to the full episode or read the full transcript below.
I’ve actually already explained most of the concepts but haven’t tied them all together into a single term. Our brains work really well with associations and the more something relates to something else you already know, then the easier it is to learn it. That’s the real reason for this episode. It should help solidify several concepts we already talked about and give you another way to relate them.
Anytime you have an instance of a class that points to another instance which points to a third, etc., then you can imagine each of these items forming a link in a chain. I explained this as a linked list earlier in episode 40. A single path through a binary tree from parent node to child node is also a chain.
An interesting property of chains is that you can split them anywhere and have two perfectly good chains. And you can join them back together again. But here’s the interesting part. You don’t need to join a portion of a chain back to where it was originally connected. Now this won’t always work very well with a binary tree but for a linked list if you want to move several consecutive items from one list to another, then you might as well move the piece of chained items and leave it intact during the move.
This is exactly what you’d do in real life if you wanted to remove several feet of chain from one metal chain and attach it to the end of another chain. Just break one link, open the broken link, and detach the chain portion to be moved. Then you might be able to reuse the broken link or maybe you need a new link but you can then use a joining link to attach the section onto the end of another chain.
In programming, anytime you can move a bunch of items by just changing a single item, you have a good solution.
Chains don’t always have to be instance of object though. When you have a methodA that calls methodB which call methodC, etc., this is also a chain. This type of chain will be super important to understand when I explain exception handling. Don’t worry, that’s on my list for a future episode. I want to prepare you a bit more though before we get to exception handling. For right now, just understand that each method called had to be called from some other method somewhere. A method also cannot call two other methods simultaneously on the same thread. See what I mean, now I’ve brought up the topic of threads. Let’s not go there for right now. Just know that when a method calls another method, then the method doing the calling stops and has to wait for the called method to complete and return before it can continue. The called method could in turn call other methods of its own and then it also has to stop and wait for each of those methods to complete.
When a method completes and returns to the calling method, you can think of this as removing the current last link from a chain of methods. As your program executes, it will call various methods which could call into a deep nesting of methods before backing out again. You program probably won’t back out all the way but this chain of methods will fluctuate in length as it calls methods and returns from them. This is called a call chain or a call stack.
Another reason chains are a good way to think about methods is because you can imagine them forming loops too. Just like how you can bring the end of a real metal chain around and attach it to any other link in the chain, you can do the same thing with methods. This is called recursion and is a very powerful technique. You need to be aware of it or you can easily create a program that crashes when it runs out of stack space. This would sort of be like building a real life metal chain and running out of links. We’ll need to wait for another episode for recursion too or this topic will just get too long.
You’ve also learned about class inheritance. Well, you guessed it, this also forms a class chain. Pretty much any time you have a parent-child relationship, you can think of this as a chain. You can have derived classes that all implement the same method either virtually or by hiding the parent method of the same name. Then inside a method in a child, it’s often convenient to call the parent’s version of this same method. This forms a call chain by walking along the class chain of methods.
Let me give you a simple example. Let’s say you have a class called Animal with a virtual method called eat and you have a child class or a derived class called Cat which overrides the eat method. Good programming says that you shouldn’t repeat code so what do you do in the eat method that belongs to the Cat class? You do only those things that a cat would do. Things that are specific to cats. But you probably want to also call the parent class Animal’s eat method too so that it can do whatever animals in general need to do when eating. This is a design decision. I’m not trying to explain that this always needs to be done like this. Just that if you do call into the parent’s version of a method, then you’re doing so because of the class chain.
I’ll explain the final chaining topic today right after this message from our sponsor.
( Message from Sponsor )
In many ways, this last form of chaining is the most interesting. It’s certainly a bit more involved than the other types of chains that I just described. I’m talking about operator chaining.
Let’s start with a couple integer variables b and c. Let’s say that b has the value 5 and c has the value 10. Then let’s create the following simple statement:
◦ int a = b + c;
There are two operators here, the assignment operator and operator +. Notice how I didn’t call operator + the addition operator. You could call it this but it’s more common to refer to it as operator plus.
Now, the assignment operator and operator + have different precedence levels so we know that b will be added to c first before that value gets assigned to a. But how does this work in detail?
You can think of each operator as just another method. That’s what they are really. And like any method, there can be a return value. The operator + is a binary operator that needs two operands. We have those two operands in this example as b and c. This operator + method receives the two values as parameters so it gets the value 5 and the value 10 and adds them together to get 15. It then returns the value 15 as its return value.
The return value from the operator + then chains to the next operator which is the assignment operator. The assignment operator is also a binary operator and needs two values. The first value is a reference of where to put the second value. The assignment operator in this example is passed a reference to the integer a and the value 15. It then assigns 15 to a. And we’re done, right? Not exactly. While we’re done for this example, there is a little more to this story.
You see, the assignment operator also has a return value. We’re not using the return value from the assignment operator in the previous example. But let me show you an example where it is used. Let’s change the simple statement to read like this:
◦ int a = b = c;
This may be a bit surprising to you or maybe you’ve already seen something like this. All it really means is that we want a, b, and c to all have the same value. So we have a statement with two assignment operators. Since they’re the same operator, then they’re definitely going to have the same precedence. If this was operator +, then we would add b to a and then add c to that. That’s because addition is evaluated from left to right. But assignment is evaluated from right to left.
So when you have a statement that says a = b = c, then it’s the second assignment operator that runs first. This assigns the value in c which is 10 in our example to b. The variable b used to have the value 5 but after this it now has the value 10 that it got from c.
This is where the return value from the assignment operator becomes important and forms the glue that holds this whole statement together. The return value from operators is what allows them to be chained together. When the second assignment operator returns, it returns a reference to its first operand. That will be a reference to the variable b in this example. That reference is what gets passed to the first assignment operator as its second parameter. The first parameter is a. This assigns the value currently in b which is now 10 to the variable a which is waiting for its initial value. The first assignment operator then does the same thing and returns a reference to a. But in this example, that return value is not needed since the chaining is done. Had there been other variables, then the pattern would have repeated. You could have int a = b = c = d = e etc. Each call to an operator just returns a value that will allow it to be chained to any other operators in the same statement.