Static variables and methods are those that belong to the class itself, rather than to individual instances of the class.
This means that there is a single copy of each static variable or method, shared by all instances of that class.
For example, if you had a Person
class and each instance had its own book where it kept its own data, the static variables and methods would be like a large shared whiteboard that everyone can read from and write to.
Static methods represent an approach to procedural programming, without straying (much) from the paradigms of object-oriented programming. Meanwhile, static variables are somewhat similar to “global variables”.
Additionally, they are slightly more convenient to use than instance variables, because they do not require creating an instance before using them.
Static Variables and Methods
Static Variables
Static variables belong to the class. This means there is a single copy of the variable, shared by all instances of the class.
Any method, both instance and static, can potentially access the variables (as long as the access modifiers allow it).
Static variables can be used to store data that must be accessible to all instances, to maintain a global state, or constants.
Static Methods
Static methods are functions that belong to the class and not to an instance of the class.
These methods cannot access instance variables or methods directly, because for them, instances do not exist (but they can access other static variables and methods).
Practical Case
Let’s return to the practical case of the Person
class that we had when looking at instance variables and methods. This time, we have added a static variable Counter
and a static method example IncrementCounter()
.
- stringName
- stringId
- static intCounter
- static voidIncrementCounter()
First of all, from anywhere in the code I can access static variables and methods. That is, it is possible to do this from anywhere,
Person.Counter = 12;
Person.IncrementCounter();
Of course, “from anywhere” implies that all instances can also access the variables. Even in the class definition itself.
In fact, one typical example of static variables and methods is to add a counter that counts the instances generated from a class (in the end, we will see that this is not a good idea 🙅♂️, except to make an example).
If we wanted to do that, we would simply increment the static variable Counter
in the constructor of Person
.
class Person
{
Person()
{
Person.Counter++;
// we could also call the static method
//Person.IncrementCounter();
}
}
As I said, this idea is not the best in the world, but it illustrates well how we can use static variables and methods from anywhere in the code.
Examples in Different Languages
Finally, let’s see how different languages implement the concept of static variables and methods.
In C#, static variables and methods are defined using the keyword static
.
public class Counter
{
// Static variable
public static int Counter;
// Static method
public static void IncrementCounter()
{
Counter++;
}
}
// Usage
Counter.IncrementCounter();
Console.WriteLine(Counter.Counter);
In C++, static variables and methods are defined using the keyword static
.
#include <iostream>
class Counter {
public:
// Static variable
static int Counter;
// Static method
static void IncrementCounter() {
Counter++;
}
};
// Definition of the static variable
int Counter::Counter = 0;
// Usage
int main() {
Counter::IncrementCounter();
std::cout << Counter::Counter << std::endl;
return 0;
}
In JavaScript, static variables and methods are defined using the keyword static
. These variables and methods belong to the class instead of individual instances of the class.
class Counter {
// Static variable
static counter = 0;
// Static method
static incrementCounter() {
Counter.counter++;
}
}
// Usage
Counter.incrementCounter();
console.log(Counter.counter);
In TypeScript, static variables and methods are defined using the keyword static
.
class Counter {
// Static variable
static counter: number = 0;
// Static method
static incrementCounter(): void {
Counter.counter++;
}
}
// Usage
Counter.incrementCounter();
console.log(Counter.counter);
In Python, static variables and methods can be simulated using @classmethod
decorators and class variables.
class Counter:
# Static variable
counter = 0
# Static method
@classmethod
def increment_counter(cls):
cls.counter += 1
# Usage
Counter.increment_counter()
print(Counter.counter)
Best Practices Tips
The million-dollar question with static methods is when to use a static method and when not to? And throughout your life, I can tell you that you will change several times between loving them and hating them😘.
In principle, my advice is to avoid static methods and variables whenever possible. The main reason is that you cannot override them, nor can you easily replace them, and… (basically, they don’t give you much flexibility).
Once your code “gets hooked” on a static method, you are very much tied to it. This means that it will give you maintenance problems in the future, testing issues, problems for mocking… it will give you problems all around.
MyClass.DoSomething(); // once you put that in, you have to live with it forever
Moreover, most of the time it doesn’t make sense to use them. In the example we provided, which is the typical one used, of a counter that counts the number of Person
instances created… well, in real life, that’s a messy approach.
If you are going to do something like that, the logical thing is to have a higher object PersonManager
or PersonGroup
, or whatever, that holds that information which is typically used in examples to illustrate static variables and methods.
public class PersonManager
{
public int Counter;
public Person GeneratePerson() {
//.. whatever
}
}
However, we must not deny that static methods bring simplicity to programs. For example, imagine you create a library that downloads videos from the Internet. A static method might be easier to use.
// it's easier to use this
VideoDownloader.Download("video_url");
// than this
var videoDownloader = new VideoDownloader();
videoDownloader.Download("video_url");
In summary, my advice is to avoid static methods as much as possible. Only use them if they make sense for their original purpose, which is isolated functions that do not require their own variables or information.
The typical example is a function for mathematical functions, where you simply want to have the functions grouped, but it is still procedural programming. There, it makes sense for them to be static.
Or, when you want to provide a simpler way for the developer to use a library. And usually always as a shortcut for an alternative method that offers more functionality.