I work on a proprietary project that uses quite a lot of factories of one form or another. Most of them don't instantiate the class by name, fortunately, but whether new self() or new static() is used to instantiate varies depending on the developer.
I'm aware of the difference, but I'm curious if there's some consensus on which one is the "correct" way to go when late static binding isn't technically required. For instance, new static() is often found in service classes that will almost certainly never be subclassed. It's obviously important in abstract classes, but my preference would be to use new self() where I don't expect a subclass.
Questions that address the technical difference:
New self vs. new static
what means new static?
Why return new static? (PHP)
What I'm curious about:
Is there a performance hit to using late static binding?
Are there code maintenance implications to adopting one practice? Eg. If I subclass a class using new self(), I have to override/change all such cases, but maybe that's not a bad thing if my constructor changes.
Is there a documented best practice on this? We use PSR-2, at least aspirationally, but I don't think it covers this.
First, lets discuss the difference for a moment:
Returning new static will result in an instance of the derived class, meaning if Foo declares static method Create() (a factory method) that returns a new static, then calling Foo::Create() or self::Create() from Foo will return an instance of Foo. However, if class Bar extends Foo, and you call Bar::Create(), it'll return an instance of Bar.
Thus, if you want Bar::Create() to return an instance of Foo, you should use new self, not new static.
Considering developer expectations that static factory methods such as Create() return instances of the derived classes, I'd argue that returning the late-bound type is likely the right answer in most circumstances. However if a class is marked final (sealed, closed to extension), then it doesn't matter. Assuming a class isn't final, (which presumes others are allowed to extend it), static is likely the right choice.
As far as performance goes; given PHP is interpreted, I can't imagine it has significant performance implications. This is really a discussion about what is more correct/semantic, and to reiterate, I think returning a new static is the correct answer most of the time, with returning a new self being the exception in specific circumstances.
Note that this question is actually pretty similar to here: Is it possible to overuse late static binding in PHP?. You may find that answer useful, too.
Related
Just startet to feel the real usefulness for classes and methods (Object Oriented Programming) in PHP. However I still lack the understanding and experience declaring methods and variables the proper way.
I what cases should I declare a method/variable static VS declaring it non-static? What questions do I ask myself to answer this question?
Static means that you can access the functions without first creating an instance of the class. This makes it a lot like a normal function. You tend to make functions static if you want to group functions together that are related, but do not need a specific instance of the class to run.
Non-static members require an instance of the class. Typically you will use this.
If we have a class Circle and it has function area(), then it would be non-static as it needs a specific circle to find the area of. Now imagine we have a PrintText class with a printBold() function. We don't need an instance since it only depends on the inputs. However it is convenient to have the PrintText class because we could have printBold(), printItalics(), etc.
In my example I'm using the PHP framework Yii2 but I think this applies to most OO languages.
I have an ActiveRecord base class which most of my business objects extend from e.g. Project.
At the moment if I want a Project instance I call
Project::findOne(['id' => $id]);
findOne is a static method of ActiveRecord (which is part of the Yii2 framework). So this is bad form because I can't easily mock/stub the return of this call when writing unit tests.
But what's the best way to get around this?
I could create a class CActiveRecord that inherits from ActiveRecord and wrap the static call in a non-static call and use that everywhere - but then I would have to instantiate a throw-away Project object in order to get the actual instance. What if the Project object needed some heavy config to be instantiated - I would be passing random nonsense into the constructor just to get an instance.
Summary:
Simply changing statics to non-statics seems wrong - shouldn't I also move the functions somewhere else? If so, where?
The issue with static calls is the hard coupling to a specific other piece of code. Just wrapping that in a "dynamic" call doesn't make this any better:
$c = new CProject;
$c->findOne(); // Calls Project::findOne()
That's pretty darn pointless. The issue is not the syntax of -> vs. ::, the issue is that this particular code references a specific other class and that you cannot easily exchange this class for something else. You're building rigid, hardcoded dependencies between your classes/objects, which makes it hard to take them apart, which makes your code hard to test, and which makes it harder to adapt code to different situations.
The alternative is dependency injection:
function foo(Project $project) {
$p = $project->findOne();
}
This function is not coupled to any one specific Project class, but to a class which simply offers an interface akin to Project. In fact, Project could even be simply an interface. Which specific class and method is getting called here then is decided somewhere completely different, like your dependency injection container; or simply the caller of this code.
This makes it a lot easier to take this code apart and put it back together in different ways, as necessary for the situation at hand. That's not to say it can't work and that you should never use static calls at all, but you really need to be aware of what cross-dependencies you're establishing with every hardcoded class name, and whether that may or may not cause a problem down the line. For even moderately complex and/or growing software projects, it will almost certainly cause friction in some form or another eventually.
See How Not To Kill Your Testability Using Statics for a longer in-depth article.
Ok guys I am struggling to understand why there is a need of singleton.
Let's make a real example: I have a framework for a my CMS
I need to have a class that logs some information (let's stick on PHP).
Example:
class Logger{
private $logs = array();
public function add($log) {
$this->logs[]=$log;
}
}
Now of course this helper object must be unique for the entry life of a page request of my CMS.
And to solve this we would make it a singleton (declaring private the constructor etc.)
But Why in the hell a class like that isn't entirerly static? This would solve the need of the singleton pattern (that's considered bad pratice) Example:
class Logger {
private static $logs = array();
public static function add($log) {
self::$logs[]=$log;
}
}
By making this helper entirely static, when we need to add a log somewhere in our application we just need to call it statically like: Logger::add('log 1'); vs a singleton call like: Logger::getInstance()->add('log 1');
Hope someone makes it easy to understand for me why use singleton over static class in PHP.
Edit
This is a pretty nice lecture on the singleton vs static class for who is interested, thanks to #James. (Note it doesn't address my question)
Many reasons.
Static methods are basically global functions that can be called from any scope, which lends itself to hard to track bugs. You might as well not use a class at all.
Since you cannot have a __construct method, you may have to put an init static method somewhere. Now people in their code are unsure if the init method has been called previously. Do they call it again? Do they have to search the codebase for this call? What if init was somewhere, but then gets removed, or breaks? Many places in your code now rely on the place that calls the init method.
Static methods are notoriously hard to unit test with many unit testing frameworks.
There are many more reasons, but it's hard to list them all.
Singletons aren't really needed either if you are using DI.
A side note. DI allows for your classes not to rely on each other, but rather on interfaces. Since their relationships are not cemented, it is easier to change your application at a later time, and one class breaking will not break both classes.
There are some instances where single state classes are viable, for instance if none of your methods rely on other methods (basically none of the methods change the state of the class).
I use singletons, so I can tell you exactly why I do it instead of a static function.
The defining characteristic of a singleton is that it is a class that has just one instance. It is easy to see the "just one instance" clause and forget to see the "it is a class" clause. It is, after all, a normal class object with all the advantages that that brings. Principly, it has its own state and it can have private functions (methods). Static functions have to do both of these in more limited or awkward ways.
That said, the two complement each other: a static function can be leveraged to return a singleton on the same class. That's what I do in the singleton I use the most often: a database handler.
Now, many programmers are taught that "singletons are bad, mm'kay?" but overlook the rider that things like are usually only bad when overused. Just like a master carver, an experienced programmer has a lot of tools at his disposal and many will not get a lot of use. My database handler is ideal as a singleton, but it's the only one I routinely use. For a logging class, I usually use static methods.
Singletons allow you to override behavior. Logger::add('1') for example can log to different devices only if the Logger class knows how. Logger::getLogger()->add('1') can do different things depending on what subtype of Logger getLogger() returns.
Sure you can do everything within the logger class, but often you then end up implementing the singleton inside the static class.
If you have a static method that opens a file, writes out and closes it, you may end up with two calls trying to open the same file at the same time, as a static method doesn't guarantee there is one instance.
But, if you use a singleton, then all calls use the same file handler, so you are always only having one write at a time to this file.
You may end up wanting to queue up the write requests, in case there are several, if you don't want them to fail, or you have to synchronize in other ways, but all calls will use the same instance.
UPDATE:
This may be helpful, a comparison on static versus singleton, in PHP.
http://moisadoru.wordpress.com/2010/03/02/static-call-versus-singleton-call-in-php/
As leblonk mentioned, you can't override static classes, which makes unit testing very difficult. With a singleton, you can instantiate a "mock" object instead of the actual class. No code changes needed.
Static classes can have namespace conflicts. You can't load 2 static classes of the same name, but you can load 2 different versions of a singleton and instantiate them under the same name. I've done this when I needed to test new versions of classes. I instantiate a different version of the class, but don't need to change the code that references that class.
I often mix singletons and static. For example, I use a database class that ensures there is only 1 connection to each master (static) and slave (singleton). Each instance of the db class can connect to a different slave, if a connection to the same slave is requested, the singleton object is returned. The master connection is a static object instantiated inside each slave singleton, so only 1 master connection exists across all db instantiated objects.
I have been writing a PHP class that is exactly 450 lines long and it contains 14 static methods and 4 static properties as well as 6 constants (and private __construct() and __clone()).
I am wondering here is that am I doing something wrong, is my class evil?
When you use the class, you always call a single method like:
MyClass::coolMethod();
and then you leave it alone altogether so it feels that it would be stupid to make it constructable?
There's really not much point in constructing objects out of it, because it is more like a tool that contains a few methods that you can just call directly.
Actually, out of those 14 methods, 7 of them are public -- the rest are private for the class to use.
You should avoid static as much as global.
Statics give you the same disadvantages globals give you. Whenever you are using any class methods, you are hardcoding a dependency on that class into the consuming code. The result is less maintainable tightly coupled code. This can easily be avoided by avoiding statics altogether and a disciplined use of Dependency Injection.
You cannot inject and pass around static classes, so for instance when you have to unit-test them, you cannot mock them (or at least only with some effort). It's just plain painful. Static methods are death to testability.
Also, keep in mind that classes should do only one thing. They should have a single responsibility. Go through your class to see if there is stuff in there that's better placed somewhere else to avoid writing a God Class.
It depends on the purpose of this class. If the methods are mostly incoherent in terms of data, this is a perfectly valid solution of grouping functions (now methods). This is a very bad idea if you need to share values between functions, since that would be more than a simple list of functions, grouped under a common name. Namespaces are another option, but if you're using a PHP-version lower than 5.3, this is probably the best solution.
This is like saying, "I have a house with four bedrooms. Is that bad?"
Static methods are neither good nor bad. Having fourteen methods is neither good nor bad. Having fourteen static methods is, by extension, neither good nor bad.
If in your fourteen methods you're going to great lengths to simulate object instances, or to simulate inheritance, then something has gone horribly wrong. PHP will let you create instances, and supports inheritance, so it would be silly to try to simulate them any other way.
But if you're just using your class essentially like a namespace, where the functions and data all work together but there are no individual instances of the class to contend with, there's absolutely nothing wrong with that.
Not bad. However, with all those static props, you might want to consider making this a singleton.
Here is some singleton code I am using in the framework I am building. You can tear it apart and make it the sole public method for your class that returns the one version of itself.
class ClassName {
function getInstance()
{
static $instance;
if (!isset($instance))
{
$instance = new ClassName();
}
return $instance;
}
}
You would use this, then, by doing ClassName::GetInstance()->othermethod();
The class can then have tons of private values and otherwise gain all the nice things you have with an object.
I would say that no, it isn't bad. In fact that was the only way to fake certain behavior before. It was for instance a way to fake namespaces. One could encapsulate functions in static classes instead of having them "out in the free". So allot of php developers are familiar with this and it won't actually confuse most people. What you SHOULD try to do nowadays though is to make use of PHP's "new" namespace feature and if needed combine it with a singleton pattern if you actually need to store data in an object format. You could just as well have a "global" variable contained in your namespace and that could work fine at times to. But take a look at namespaces and see if that fits you in any way and after that see if singleton pattern might match your specific needs.
Still on the PHP-OOP training wheels, this question may belong on failblog.org. =)
What are the benefits of method chaining in PHP?
I'm not sure if this is important, but I'll be calling my method statically. e.g.
$foo = Bar::get('sysop')->set('admin')->render();
From what I've read, any method which returns $this is allowed to be chained. I just learned this is new in PHP5. Seems to me there may be speed benefits if I don't have to instantiate a whole new object (calling it statically) and just select the few methods I need from the class?
Do I have that right?
There are no significant performance benefits to using either approach, especially on a production server with byte code cache.
Method chaining is just a shorter way of writing things. Compare with the longer version:
$foo = Bar::get('sysop');
$foo -> set('admin');
$foo -> render();
It does have some quirks, though: a typical IDE (such as Eclipse) can auto-complete your code in the longer version (as long as the type of $foo is known) but needs you to document the return type of all methods to work in the short version.
It still instantiates an object; it's just never assigned to a variable. Basically, you're just calling the methods of an anonymous object.
I think any cycle-savings would be negligible, but I think the unassigned objects would be freed immediately after this line of code, so you may have some memory savings (you could accomplish the same by setting assigned objects to null when you were done with them).
The main reason people use method chaining is for convenience; you're doing a lot in one line of code. Personally, I think it's messy and unmaintainable.
if I don't have to instantiate a whole
new object (calling it statically) and
just select the few methods I need
from the class?
Wrong! To return $this, the class has to be instantiated.