When should I use static methods?

I have a class that is containing 10 methods. I always need to use one of those methods. Now I want to know, which approach is better?

class cls{
    public function func1(){}
    public function func2(){}
    .
    .
    public function func10(){}
}

$obj  = new cls;
$data = $obj->func3(); // it is random, it can be anything (func1, or func9 or ...)

OR

class cls{
    public static function func1(){}
    public static function func2(){}
    .
    .
    public static function func10(){}
}

cls::func3(); // it is random, it can be anything (func1, or func9 or ...)

Solution 1:

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.

Solution 2:

The answer depends on what those methods do. If you're using them to mutate the state of the object at hand, you need to use the instance method calls. If they're independent functionality, then you can use the static versions, but then I'd question why they're part of a class at all.

Solution 3:

So, there is a very basic difference in static methods.

To use static functions, you don't need to initialise the class as an object. For example, Math.pow(), here .pow() (in Java; but the explanation still holds) is a static method.

The general rule is to make the helper methods static.

So, for example, if you have a Math class, you wouldn't want to fill the garbage collector with classes which just help other, more important, classes.

You can use it as dynamic initializers, if you please!

Let's say you have a class RSAEncryptionHelper, now you can generally initialize it without any parameters and this will generate an object with a key size of (say) 512 bits; but you also have an overloaded object constructor which gets all of the properties from other classes:

$a = new RSAEncryptionHelper::fromPrimeSet(...);