My JavaScript book is out! Don't miss the opportunity to upgrade your beginner or average dev skills.

Thursday, March 22, 2007

PHP 5 developers teach us what does static keyword mean (and this is a feature!)

PHP 5 introduced a "new" keyword called static.
You can read here what does this keyword mean when it's applied to one method.

As You can read in documentation page
Declaring class members or methods as static makes them accessible without needing an instantiation of the class. A member declared as static can not be accessed with an instantiated class object (though a static method can).

They put last tiny point inside brackets as it's not a really important point to analize!

As You know, with PHP4 every method should be used as static one.
The difference between PHP 4 and PHP 5 seems to be this one:
The big difference between php 4 and php 5 is that a method declared as "static" does not have $this set. You'll get a fatal error, in fact, if you try to use $this in a static method.

Well ... static method cannot have a $this reference inside its scope but every static method is inherited into every instance ... this is absolutely hilarious:

  1. You can't call with the same name two different methods (one static, for class and one metod for instances)

  2. You can't overload manually instance method

  3. Static methods are inherited while static parameters cannot be used from instances

  4. You can't use $this reference even if You're calling method from an instance (wow, it's really OO)



To solve PHP 5 static method logic You have to forget static keyword.

class StaticString {
private $content = '';
function __construct($content){
$this->content = $content;
}
// I need different methods, not static one inherited!!!
function write($what = null){
echo func_num_args() === 0 ? $this->content : $what->get(), '
';
}
function get() {
return $this->content;
}
}

StaticString::write(new StaticString('static'));
$test = new StaticString('instance');
$test->write();

The above example shows You how to "solve" static inheritance problems, based on sent arguments (then it's a fake method overload) but shows obviously an E_STRICT notice.

So, at this point, we need a workaround to make a language feature "less buggy and more featurely" ... but static keyword shouldn't be implemented if the diference is only that you can't use instance reference inside one of these method.

This is another example, based on Singleton pattern:

class Singleton {

static private $instance;
static private $init = false;

public final static function instance(){
if(!Singleton::$init) {
Singleton::$instance = new Singleton();
Singleton::$init = true;
}
return Singleton::$instance;
}
}

$test = Singleton::instance();
var_dump($test->instance() === $test);

WoW! ... my Singleton instance inherits Singleton pattern, it's amazing!

Obviously, C# and other program languages doesn't assign static class methods into instances ... and the reason is:
If you are wanting absolutely "perfect" OO, there are plenty of other languages that will provide exactly the straightjacket and punishment you desire. If you want to code efficient, easy to maintain, working programs, use PHP.

To code efficient, easy to mantain I need a clear Object Oriented logic ... and if You're thinking about C++ there's a little difference ...

C++ instances inherit static methods and static parameters too but the big difference is that if you don't declare a class method as static, You can't use them as static method (and You can't use parameters too).

static method and public (instance) one are two different things (as you know) ... but hey, cellog gives me a fantastic, "pure OO way", example to solve my debug problem

class ExampleClass {

public $StaticExample;

public final function __construct(){
// bye bye public *parameter*
$this->StaticExample = create_function('$never', 'return "welcome PHP5
ambiguity";');
}

public final static function StaticExample(){
echo "StaticExample", "<br />";
}
}

$test = new ExampleClass();
ExampleClass::StaticExample();
exit($test->StaticExample());

That's not portable, not scalable ... absolutely a bad solution ... but it could be simply solved with this code

call_user_func_array(get_class($a), 'method', $args);

And "WoW" again! .. that's what I call OOP!!!

Thank you PHP 5 developers to introduce static methods, I hope PHP 6 will be more Object Oriented and less ambiguous than version 5.

Best regards!

[edit]
This is my bug report ... pardòn, bogus report:
http://bugs.php.net/bug.php?id=40886

4 comments:

Albano Daniele Salvatore said...

Hi,

this is a BIG non-sense feature :)

Infact if someone decide to use the static keyword is because he need to use a specific method as STATIC.
It is said to be an expected behaviour, something that php developer decided to implement because it is considered useful, but this "feature" make the code ugly and slower because the code into the method declared as static need to check if it is used as static or not.

Pratically the static keyword simply say to php to not declare the $this variable, nothing more, but it isin't declared however if i call a normal method as static!

Another strange flavour of php :)

Paul said...

Interestingly, the same behaviours appear in Java. Static methods may be used by instances with instance method notation, but of course with no instance state).

Using an instance method statically causes a compilation error.

Andrea Giammarchi said...

Ok Paul but I suppose that Java has not problems with a non static overload, as is for C++ so if You read examples on Part 2 You'll see that Java can simply do what I was looking for.

Only PHP seems to be not able to produce my expected result and there's no way to overload a static method.

Anonymous said...

nice post.