When to Use Static Methods

When to use static methods

One rule-of-thumb: ask yourself "Does it make sense to call this method, even if no object has been constructed yet?" If so, it should definitely be static.

So in a class Car you might have a method:

double convertMpgToKpl(double mpg)

...which would be static, because one might want to know what 35mpg converts to, even if nobody has ever built a Car. But this method (which sets the efficiency of one particular Car):

void setMileage(double mpg)

...can't be static since it's inconceivable to call the method before any Car has been constructed.

(By the way, the converse isn't always true: you might sometimes have a method which involves two Car objects, and still want it to be static. E.g.:

Car theMoreEfficientOf(Car c1, Car c2)

Although this could be converted to a non-static version, some would argue that since there isn't a "privileged" choice of which Car is more important, you shouldn't force a caller to choose one Car as the object you'll invoke the method on. This situation accounts for a fairly small fraction of all static methods, though.

When should I use static methods?

It is an interesting subject. I'm gonna give you a design oriented answer.

In my opinion, you should never use a static class/function in a good OOP architecture.

When you use static, this is to call a function without an instance of the class. The main reason is often to represent a service class which should not be instantiated many times.

I will give you 3 solutions (from the worst to the best) to achieve that:

Static

A static class (with only static functions) prevent you from using many OOP features like inheritance, interface implementation. If you really think of what is a static function, it is a function namespaced by the name of its class. You already have namespaces in PHP, so why add another layer?

Another big disadvantage is that you cannot define clear dependencies with your static class and the classes using it which is a bad thing for maintenability and scalability of your application.

Singleton

A singleton is a way to force a class to have only one instance:

<?php

class Singleton {
// Unique instance.
private static $instance = null;

// Private constructor prevent you from instancing the class with "new".
private function __construct() {
}

// Method to get the unique instance.
public static function getInstance() {
// Create the instance if it does not exist.
if (!isset(self::$instance)) {
self::$instance = new Singleton();
}

// Return the unique instance.
return self::$instance;
}
}

It is a better way because you can use inheritance, interfaces and your method will be called on an instanciated object. This means you can define contracts and use low coupling with the classes using it. However some people consider the singleton as an anti pattern especially because if you want to have 2 or more instances of your class with different input properties (like the classic example of the connection to 2 different databases) you cannot without a big refactoring of all your code using the singleton.

Service

A service is an instance of a standard class. It is a way to rationalize your code. This kind of architecture is called SOA (service oriented architecture). I give you an example:

If you want to add a method to sell a product in a store to a consumer and you have classes Product, Store and Consumer. Where should you instantiate this method? I can guarantee that if you think it is more logical in one of these three class today it could be anything else tomorrow. This leads to lots of duplications and a difficulty to find where is the code you are looking for. Instead, you can use a service class like a SaleHandler for example which will know how to manipulate your data classes.

It is a good idea to use a framework helping you to inject them into each others (dependency injection) in order to use them at their full potential. In the PHP community, you have a nice example of implementation of this in Symfony for instance.


To sum up:

  • If you do not have a framework, singletons are certainly an option even if I personally prefer a simple file where I make manual dependency injection.

  • If you have a framework, use its dependency injection feature to do that kind of thing.

  • You should not use static method (in OOP). If you need a static method in one of your class, this means you can create a new singleton/service containing this method and inject it to the instance of classes needing it.

When should I use static methods in a class and what are the benefits?

Your description of a static variable is more fitting to that found in C. The concept of a static variable in Object Oriented terms is conceptually different. I'm drawing from Java experience here. Static methods and fields are useful when they conceptually don't belong to an instance of something.

Consider a Math class that contains some common values like Pi or e, and some useful functions like sin and cos. It really does not make sense to create separate instances to use this kind of functionality, thus they are better as statics:

// This makes little sense
Math m = new Math();
float answer = m.sin(45);

// This would make more sense
float answer = Math.sin(45);

In OO languages (again, from a Java perspective) functions, or better known as methods, cannot have static local variables. Only classes can have static members, which as I've said, resemble little compared to the idea of static in C.

When to use static variables/methods and when to use instance variables/methods in Java?

At novice level :

Use instance variables when : Every variable has a different value for different object. E.g. name of student, roll number etc..

use static variables when : The value of the variable is independent of the objects (not unique for each object). E.g. number of students.

When to use and not to use static function?

You use static when the function doesn't depend on a specific object that the method is being applied to. How that applies to your application depends on its design.

For instance, if you have a class for dealing with dates and times, and it contains a function to return the current timestamp, it doesn't need to be applied to a specific date object -- it's the same for any date. So it could be a static function.

Static functions may be necessary if you need to run some functions before creating any instances of the class. If you use the Factory pattern, you will use a method to create instances in the first place. This will necessarily be a static method.

when to use static method or simple class method?

You can find the long answer here: How Not To Kill Your Testability Using Statics

The TL;DR version of it is:

  • A static method is nothing more than a namespaced function, Foo::bar() does not significantly differ from foo_bar().
  • Whenever you call a static method, or a function for that matter, you're hardcoding a dependency. The code that reads $bar = Foo::bar(); has a hardcoded dependency to a specific Foo class. It is not possible to change what Foo refers to without changing that part of the source code.
  • An object is a "soft" dependency. $bar = $foo->bar(); is flexible, it allows room to change what $foo refers to. You use this with dependency injection to decouple code from other code:

    function baz(Foo $foo) {
    $bar = $foo->bar();
    ...
    }
  • You can call Foo::bar() anytime from anywhere. If Foo::bar has some dependency it depends on, it becomes hard to guarantee that this dependency is available at the time you're calling the method. Requiring object instantiation requires the object's constructor to run, which can enforce requirements to be set up which the rest of the methods of the object can depend on.

  • Constructors together with dependency injecting objects into other functions are very powerful to

    1. create seams in your codebase to make it possible to "take it apart" and put it together in flexible ways
    2. put checks into strategic places to ensure requirements are met for certain parts of the code (at object instantiation time the constructor enforces a sane state of its little part of the world, its object), which makes it a lot easier to localise and contain failures.

    Think of it like compartmentalising your app and putting firewalls between each compartment with a supervisor in charge of each one; instead of everyone just running around in the same room.

  • Any time you write new Class, you may as well write Class::staticMethod(), the hardcoded dependency is the same.

So the decision comes down to:

  • What are the requirements of this class? Does it need to ensure certain preconditions are met before any of its code can run (e.g. a database connection needs to be available), or are all methods just self-contained little helper methods?
  • How likely are you to maybe want to substitute this class for another class? Does this class produce side effects (e.g. writing to a file, modifying some global state) which may not always be desirable and hence a different version of it may be useful under some circumstances?
  • May you need more than one instance of this class at the same time, or is the nature of the class such that there are no individual instances needed?

Start using unit tests, which require you to take your app apart and test each little part individually to ensure it works, and you'll see where the advantage of object instantiation and dependency injection lie.

When should I write Static Methods?

It gives a better idea of the intent when you use a static factory -- it also lets you have different factories that take the same argument types but have a different meaning. For example, imagine if Bitmap had LoadFromResource(string) -- it would not be possible to have two constructors that both took string.

EDIT: From stevemegson in the comments

A static factory can also return null, and can more easily return an instance that it got from cache. Many of my classes have a static FromId(int) to get an instance from a primary key, returning an existing cached instance if we have one.

Python when to use instance vs static methods

The functions you have wrote in your code are instance methods but they were written incorrectly.
An instance method must have self as first parameter

i.e def build_url(self, url_paramater1, url_parameter2, request_date):

Then you call it like that

get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)

This self parameter is provided by python and it allow you to access all properties and functions - static or not - of your Get class.

If you don't need to access other functions or properties in your class then you add @staticmethod decorator and remove self parameter

@staticmethod
def build_url(url_paramater1, url_parameter2, request_date):

And then you can call it directly

Get.build_url(url_paramater1, url_parameter2, request_date)

or call from from class instance

get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)

But what is the problem with your current code you might ask?
Try calling it from an instance like this and u will see the problem

get_inst = Get()
get_inst.build_url(url_paramater1, url_parameter2, request_date)

Example where creating an instance is useful:
Let's say you want to make a chat client.

You could write code like this

class Chat:
def send(server_url, message):
connection = connect(server_url)
connection.write(message)
connection.close()

def read(server_url):
connection = connect(server_url)
message = connection.read()
connection.close()
return message

But a much cleaner and better way to do it:

class Chat:

def __init__(server_url):
# Initialize connection only once when instance is created
self.connection = connect(server_url)

def __del__()
# Close connection only once when instance is deleted
self.connection.close()

def send(self, message):
self.connection.write(message)

def read(self):
return self.connection.read()

To use that last class you do

# Create new instance and pass server_url as argument
chat = Chat("http://example.com/chat")
chat.send("Hello")
chat.read()
# deleting chat causes __del__ function to be called and connection be closed
delete chat


Related Topics



Leave a reply



Submit