Hi internals@,
PHP supports Object Oriented Programming (aka OOP), and one of the ground rule of OOP is polymorphism. Polymorphism can currently be used in your PHP code, however in some cases, using it can be a PITA because PHP does not natively implement the Null Object Pattern.
Below, is a (very) simple use case to illustrate this pattern:
interface logger
{
function messageIs($error);
}
class parser
{
private $logger;
function __construct(logger $logger)
{
$this->logger = $logger;
}
function parseData(parser\data $data)
{
…
# Error, log it!
$this->logger->messageIs($error);
…
}
}
Now imagine you don’t want to log any error.
One solution is to add a default value null
to its argument:
class parser
{
…
function __construct(logger $logger = null)
{
$this->logger = $logger;
}
…
}
However, this (very) basic solution has a drawback: the developer must now check $this->logger
everytime before using it:
class parser
{
…
function dataProviderIs(data\provider $dataProvider)
{
…
# Error, log it!
if ($this->logger)
{
$this->logger->messageIs($error);
}
…
}
}
A more elegant way to avoid this condition everywhere is to use the Null Object Pattern:
class blackholeLogger implements logger
{
function messageIs($serror) {}
}
class parser
{
…
function __construct(logger $logger = null)
{
$this->logger = $logger ?: new blackholeLogger;
}
…
}
It’s a much better solution than the previous one because code complexity is not increased by this if
statement, and code readability is improved.
Imagine you use it in lots of classes: you must define lots of blackhole*
classes, and doing that can be rapidly a PITA!
Therefore we think it would be interesting to natively implement the Null Object Pattern in PHP as a class which would have the following behaviors:
- an instance can replace any interface or class in term of type hinting (so the class virtually implements or extends all classes and interfaces)
- every call to a method upon an instance return
$this
to avoid the special case of returning "no object". - an instance does absolutely nothing!
You could name this class:
blackhole
;nullObject
;UndefinedObject
;nil
(as in Smaltalk, Lisp, …);- or any other suggestion…
A pseudo coded implementation could be:
class nil extends * implements *
{
function __call($method, $arguments)
{
return $this;
}
}
With a native implementation of null pattern using nil
, the blackholeLogger
class become useless and the previous code would be:
class parser
{
…
function __construct(logger $logger = null)
{
$this->logger = $logger ?: new nil;
}
…
}
In our opinion, the only drawback to introduce Null Object Pattern natively in PHP is backward compatibility, because the name of the class would become a reserved word, so maybe it should only be implemented in a future major version, aka PHP 8.
Any feedback?