If all properties of a class are constants or static, does it make sense to make all the methods static as well?
There are many cases when using static class makes sense. Actually in php there is no such thing as static class. Any class can have static and non static methods, so when people say “static” class they generally mean a class that has only static methods, but you can’t declare your class static.
Anyway, as I said, there are many reasons when it makes perfect sense to use static methods. You don’t need to worry about passing the object around to other objects that may need it. For example, you may have a very simple logging class that has one static method log($message)
One of the most rediculous comment in this thread is this:
“Creating an instance can also save you from having to constantly type out a long class name.”
What does this suppose to mean? If you have an object you still have to type the object name, then the -> then method name.
As far as not having to type long class names, you can make them as long or as short as you want. I for example named my logger class L with the static method d (for debugging)
So anywhere in my script I just write L::d(‘some debugging info here’);
And I don’t have to type any long class names as you can see.
Another case when static methods make sense if when you pass all required data, often other objects as parameters to static methods. Then your static method has everything it needs to process data and return result or even to manipulate the passed objects.
For example, you may have a static method that checks permissions. You would pass the user object and resource object to a method and it would check and see if the resource is owned by the user
Like this
AccessCheck::isOwner($object, $user);
This is another case where it makes sense to have static method so you don’t have to pass the object around and can call it from anywhere.
While it is true a class cannot be declared static per se, the structure of PHP makes it very difficult for the static methods and members of a class to interact with the non-statics. It’s rarely useful to intermix them.
And “AccessCheck::isOwner” offers precious few advantages over “accessCheckIsOwner” as a top level function. While variables can be attached to a static and be visible anywhere if they are public, they are also modifable from anywhere and therefore offer no real advantage over placing them in the $GLOBALS array except, perhaps, to prevent your application from accidently colliding with a PHP library provided by a third party.
Before namespaces the things where used as psuedo namespaces on functions, and now that we have namespaces their only remaining purpose is to provide a psuedo namespace for variables.
The downfall of this is they offer few good ways to control changes to their data. Controlling access involves protecting them, but then you have to write a getter and setter, and the lack of a magic method to this purpose makes accessing them that much more clumsy.
Nope. While PHP 5.3 has late static binding its difficult to work with. I wouldn’t use a static class for anything I need to extend. Here recently I’ve stopped using static classes entirely because of the Dependency Injection concerns their use creates.
Yes. Such a class is referred to as a singleton. If that is always the context of the class you might want to define the constructor to throw an exception to prevent the instantiation of the object at all.
Thanks for the advice. It’s only a very simple class and being used in one place on the website so I think I’ll go with making it static as Michael suggests.
If it was needed in the future to store instance data, would it really be that much hard work to change? Wouldn’t it just be a case of creating a new class that extends the static one, then you could use the new class for storing the instance data in?
A singleton is a class which, if instantiated at all, is only instantiated once in the system.
An all static class (all members and methods static) is almost forced into being a singleton since any instantiated copy would not be able to create personal copies of any of the data members. In any event static classes as the OP described are the best method in PHP of following the pattern.
BTW, singletons by design restrict what you can do with them in the future, so be careful whenever you are considering making one so you don’t have to undo the work that went into building them.
Lets just say that you could make all the methods static but you will probably find out that keeping them dynamic is easier. I sometime start off with what looks like a static class and then find out later that I really do need a bit of instance data. And then it becomes a pain to change because a given method needs to be either static or dynamic and cannot be both.
Creating an instance can also save you from having to constantly type out a long class name. You will also find that if you decide to change the name of the class then going through your code and changing all the static methods can be a pain. And in some cases you might want to pass the class to a function. Easier to pass an instance variable than it is to pass a class name.
And I think Michael Morris may have misread your original question. A static class is not a singleton.
Some folks get concerned about wasting resources when an instance is created. But it’s pretty safe to say that the tiny amount of time it takes to create an instance is not going to impact the overall script execution time nor will memory consumption suddenly sky rocket.
I rarely use static methods except for:
Authorization::isUser();
Authorization::isAdmin();
// etc.
Or maybe something like:
Random::Digit(8);
Random::String(25);
// etc.
But I don’t use those within Library classes, otherwise they become dependant on those.
Thanks for the info everyone.
<?php
class garbage
{
protected static $can = array();
private $mask;
public static function collect($mask)
{
array_push(garbage::$can, new garbage($mask), new garbage("$mask.gz"));
}
public function __construct($mask)
{
$this->mask = $mask;
}
public function __destruct()
{
file_utils::glob_delete($this->mask);
}
}
/*
garbage::collect('cache/section/*.html');
garbage::collect('cache/index.html');
*/
?>