[ACCEPTED]-When to use static vs instantiated classes-class

Accepted answer
Score: 126

This is quite an interesting question -- and 16 answers might get interesting too ^^

The 15 simplest way to consider things might be 14 :

  • use an instanciated class where each object has data on its own (like a user has a name)
  • use a static class when it's just a tool that works on other stuff (like, for instance, a syntax converter for BB code to HTML ; it doesn't have a life on its own)

(Yeah, I admit, really really overly-simplified...)

One thing about static methods/classes 13 is that they don't facilitate unit testing 12 (at least in PHP, but probably in other 11 languages too).

Another thing about static 10 data is that only one instance of it exists 9 in your program : if you set MyClass::$myData 8 to some value somewhere, it'll have this 7 value, and only it, every where -- Speaking 6 about the user, you would be able to have 5 only one user -- which is not that great, is 4 it ?

For a blog system, what could I say 3 ? There's not much I would write as static, actually, I 2 think ; maybe the DB-access class, but probably 1 not, in the end ^^

Score: 72

The main two reasons against using static 79 methods are:

  • code using static methods is hard to test
  • code using static methods is hard to extend

Having a static method call 78 inside some other method is actually worse 77 than importing a global variable. In PHP, classes 76 are global symbols, so every time you call 75 a static method you rely on a global symbol 74 (the class name). This is a case when global 73 is evil. I had problems with this kind of 72 approach with some component of Zend Framework. There 71 are classes which use static method calls 70 (factories) in order to build objects. It 69 was impossible for me to supply another 68 factory to that instance in order to get 67 a customized object returned. The solution 66 to this problem is to only use instances 65 and instace methods and enforce singletons 64 and the like in the beginning of the program.

Miško Hevery, who 63 works as an Agile Coach at Google, has an 62 interesting theory, or rather advise, that 61 we should separate the object creation time 60 from the time we use the object. So the 59 life cycle of a program is split in two. The 58 first part (the main() method let's say), which 57 takes care of all the object wiring in your 56 application and the part that does the actual 55 work.

So instead of having:

class HttpClient
{
    public function request()
    {
        return HttpResponse::build();
    }
}

We should rather 54 do:

class HttpClient
{
    private $httpResponseFactory;

    public function __construct($httpResponseFactory)
    {
        $this->httpResponseFactory = $httpResponseFactory;
    }

    public function request()
    {
        return $this->httpResponseFactory->build();
    }
}

And then, in the index/main page, we'd 53 do (this is the object wiring step, or the 52 time to create the graph of instances to 51 be used by the program):

$httpResponseFactory = new HttpResponseFactory;
$httpClient          = new HttpClient($httpResponseFactory);
$httpResponse        = $httpClient->request();

The main idea is 50 to decouple the dependencies out of your 49 classes. This way the code is much more 48 extensible and, the most important part 47 for me, testable. Why is it more important 46 to be testable? Because I don't always write 45 library code, so extensibility is not that 44 important, but testability is important 43 when I do refactoring. Anyways, testable 42 code usually yields extensible code, so 41 it's not really an either-or situation.

Miško 40 Hevery also makes a clear distinction between 39 singletons and Singletons (with or without 38 a capital S). The difference is very simple. Singletons 37 with a lower case "s" are enforced 36 by the wiring in the index/main. You instantiate 35 an object of a class which does not implement 34 the Singleton pattern and take care that 33 you only pass that instance to any other 32 instance which needs it. On the other hand, Singleton, with 31 a capital "S" is an implementation 30 of the classical (anti-)pattern. Basically 29 a global in disguise which does not have 28 much use in the PHP world. I haven't seen 27 one up to this point. If you want a single 26 DB connection to be used by all your classes 25 is better to do it like this:

$db = new DbConnection;

$users    = new UserCollection($db);
$posts    = new PostCollection($db);
$comments = new CommentsCollection($db);

By doing the 24 above it's clear that we have a singleton 23 and we also have a nice way to inject a 22 mock or a stub in our tests. It's surprisingly 21 how unit tests lead to a better design. But 20 it makes lots of sense when you think that 19 tests force you to think about the way you'd 18 use that code.

/**
 * An example of a test using PHPUnit. The point is to see how easy it is to
 * pass the UserCollection constructor an alternative implementation of
 * DbCollection.
 */
class UserCollection extends PHPUnit_Framework_TestCase
{
    public function testGetAllComments()
    {
        $mockedMethods = array('query');
        $dbMock = $this->getMock('DbConnection', $mockedMethods);
        $dbMock->expects($this->any())
               ->method('query')
               ->will($this->returnValue(array('John', 'George')));

        $userCollection = new UserCollection($dbMock);
        $allUsers       = $userCollection->getAll();

        $this->assertEquals(array('John', 'George'), $allUsers);
    }
}

The only situation where I'd 17 use (and I've used them to mimic the JavaScript 16 prototype object in PHP 5.3) static members 15 is when I know that the respective field 14 will have the same value cross-instance. At 13 that point you can use a static property 12 and maybe a pair of static getter/setter 11 methods. Anyway, don't forget to add possibility 10 for overriding the static member with an 9 instance member. For example Zend Framework 8 was using a static property in order to 7 specify the name of the DB adapter class 6 used in instances of Zend_Db_Table. It's been awhile 5 since I've used them so it may no longer 4 be relevant, but that's how I remember it.

Static 3 methods that don't deal with static properties 2 should be functions. PHP has functions and 1 we should use them.

Score: 23

So in PHP static can be applied to functions 34 or variables. Non-static variables are tied 33 to a specific instance of a class. Non-static 32 methods act on an instance of a class. So 31 let's make up a class called BlogPost.

title would be 30 a non-static member. It contains the title 29 of that blog post. We might also have a 28 method called find_related(). It's not static because 27 it requires information from a specific 26 instance of the blog post class.

This class 25 would look something like this:

class blog_post {
    public $title;
    public $my_dao;

    public function find_related() {
        $this->my_dao->find_all_with_title_words($this->title);
    }
}

On the other 24 hand, using static functions, you might 23 write a class like this:

class blog_post_helper {
    public static function find_related($blog_post) {
         // Do stuff.
    }
}

In this case, since 22 the function is static and isn't acting 21 on any particular blog post, you must pass 20 in the blog post as an argument.

Fundamentally 19 this is a question about object oriented 18 design. Your classes are the nouns in your 17 system, and the functions that act on them 16 are the verbs. Static functions are procedural. You 15 pass in the object of the functions as arguments.


Update: I'd 14 also add that the decision is rarely between 13 instance methods and static methods, and 12 more between using classes and using associative 11 arrays. For example, in a blogging app, you 10 either read blog posts from the database 9 and convert them into objects, or you leave 8 them in the result set and treat them as 7 associative arrays. Then you write functions 6 that take associative arrays or lists of 5 associative arrays as arguments.

In the 4 OO scenario, you write methods on your BlogPost class 3 that act on individual posts, and you write 2 static methods that act on collections of 1 posts.

Score: 14

Is it all just style?

A long way, yes. You 8 can write perfectly good object oriented 7 programs without ever using static members. In 6 fact some people would argue that static 5 members are an impurity in the first place. I 4 would suggest that - as a beginner in oop 3 - you try to avoid static members all together. It 2 will force you in the direction of writing 1 in an object oriented rather than procedural style.

Score: 13

I have a different approach to most answers 37 here, especially when using PHP. I think 36 all classes should be static unless you 35 have a good reason why not. Some of the 34 "why not" reasons are:

  • You need multiple instances of the class
  • Your class needs to be extended
  • Parts of your code cannot share the class variables with any other parts

Let me take one example. Since 33 every PHP script produces HTML code, my 32 framework has an html writer class. This 31 ensures that no other class will attempt 30 to write HTML as it is a specialised task 29 that should be concentrated into a single 28 class.

Typically, you would use the html 27 class like this:

html::set_attribute('class','myclass');
html::tag('div');
$str=html::get_buffer();

Every time get_buffer() is 26 called, it resets everything so that the 25 next class to use the html writer starts 24 in a known state.

All my static classes 23 have an init() function which needs to be 22 called before the class is used for the 21 first time. This is more by convention than 20 a necessity.

The alternative to a static 19 class in this case is messy. You would not 18 want every class that needs to write a tiny 17 bit of html to have to manage an instance 16 of the html writer.

Now I will give you an 15 example of when not to use static classes. My 14 form class manages a list of form elements 13 like text inputs, dropdown lists and more. It 12 is typically used like this:

$form = new form(stuff here);
$form->add(new text(stuff here));
$form->add(new submit(stuff here));
$form->render(); // Creates the entire form using the html class

There is no 11 way you could do this with static classes, especially 10 considering that some of the constructors 9 of each added class do a lot of work. Also, the 8 chain of inheritance for all the elements 7 is quite complex. So this is a clear example 6 where static classes should not be used.

Most 5 utility classes such as the ones converting/formatting 4 strings are good candidates for being a 3 static class. My rule is simple: everything 2 goes static in PHP unless there is one reason 1 why it should not.

Score: 10

"Having a static method call inside some 17 other method is actually worse than importing 16 a global variable." (define "worse")... and 15 "Static methods that don't deal with static 14 properties should be functions".

These are 13 both pretty sweeping statements. If I have 12 a set of functions that are related in subject 11 matter, but instance data is totally inappropriate, I 10 would much rather have them defined in a 9 class and not each of them in the global 8 namespace. I'm just using the mechanics 7 available in PHP5 to

  • give them all a namespace -- avoiding any name clashes
  • keep them physically located together instead of becoming scattered across a project -- other developers can more easily find what's already available and are less likely to re-invent the wheel
  • let me use class consts instead of global defines for any magic values

it's just altogether 6 a convenient way to enforce higher cohesion 5 and lower coupling.

And FWIW -- there is 4 no such thing, at least in PHP5, as "static 3 classes"; methods and properties can be 2 static. To prevent instantiation of the 1 class, one can declare it abstract, also.

Score: 7

First ask yourself, what is this object 35 going to represent? An object instance is 34 good for operating on separate sets of dynamic 33 data.

A good example would be ORM or database 32 abstraction layer. You may have multiple 31 database connections.

$db1 = new Db(array('host' => $host1, 'username' => $username1, 'password' => $password1));
$db2 = new Db(array('host' => $host2, 'username' => $username2, 'password' => $password2));

Those two connections 30 can now operate independently:

$someRecordsFromDb1 = $db1->getRows($selectStatement);
$someRecordsFromDb2 = $db2->getRows($selectStatement);

Now within 29 this package/library, there may be other 28 classes such as Db_Row, etc. to represent 27 a specific row returned from a SELECT statement. If 26 this Db_Row class was a static class, then 25 that would be assuming you only have one 24 row of data in one database and it would 23 be impossible to do what an object instance 22 could. With an instance, you can now have 21 an unlimited number of rows in an unlimited 20 number of tables in an unlimited number 19 of databases. The only limit is the server 18 hardware ;).

For example, if the getRows 17 method on the Db object returns an array 16 of Db_Row objects, you can now operate on 15 each row independently of one another:

foreach ($someRecordsFromDb1 as $row) {
    // change some values
    $row->someFieldValue = 'I am the value for someFieldValue';
    $row->anotherDbField = 1;

    // now save that record/row
    $row->save();
}

foreach ($someRecordsFromDb2 as $row) {
    // delete a row
    $row->delete();
}

A 14 good example of a static class would be 13 something that handles registry variables, or 12 session variables since there will only 11 be one registry or one session per user.

In 10 one part of your application:

Session::set('someVar', 'toThisValue');

And in another 9 part:

Session::get('someVar'); // returns 'toThisValue'

Since there is only ever going to be 8 one user at a time per session, there is 7 no point in creating an instance for the 6 Session.

I hope this helps, along with the 5 other answers to help clear things up. As 4 a side note, check out "cohesion" and 3 "coupling". They outline some very, very 2 good practices to use when writing your 1 code that apply to all programming languages.

Score: 6

If your class is static that means you can't 11 pass its object around to other classes 10 (since there is no instance possible) so 9 that means all your classes will be directly 8 using that static class which means your 7 code is now tightly coupled with the class.

Tight 6 coupling makes your code less reusable, fragile 5 and prone to bugs. You want to avoid static 4 classes to be able to pass instance of the 3 class to other classes.

And yes this is only 2 one of many other reasons some of which 1 have been already mentioned.

Score: 3

In general, you should use member variables 11 and member functions unless it absolutely 10 has to be shared between all instances or 9 unless you are creating a singleton. Using 8 member data and member functions allows 7 you to reuse your functions for multiple 6 different pieces of data, whereas you can 5 only have one copy of data on which you 4 operate if you use static data and functions. Additionally, though 3 not as applicable to PHP, static functions 2 and data lead to code being non-reentrant, whereas 1 class data facilitates reentrancy.

Score: 3

I'd like to say that there is definitely 11 a case where I'd like static variables- in 10 cross-language applications. You could have 9 a class that you pass a language to (e.g. $_SESSION['language']) and 8 it in turn accesses other classes that are 7 designed like so:

Srings.php //The main class to access
StringsENUS.php  //English/US 
StringsESAR.php  //Spanish/Argentina
//...etc

Using Strings::getString("somestring") is 6 a nice way to abstract your language usage 5 out of your application. You could do it 4 however you please but in this case having 3 each strings file have constants with string 2 values that are accessed by the Strings 1 class works pretty well.

More Related questions