
Inline adoc files when they are included exactly once. Also fix language tags because this inlining gives us better information on what language the code is written in.
115 lines
2.9 KiB
Plaintext
115 lines
2.9 KiB
Plaintext
== Why is this an issue?
|
|
|
|
References in a class to static class members (fields or methods) can be made using either ``++self::$var++`` or ``++static::$var++`` (introduced in 5.3). The difference between the two is one of scope. Confusingly, in subclasses, the use of ``++self::++`` references the original definition of the member, i.e. the superclass version, rather than any override at the subclass level. ``++static::++``, on the other hand, references the class that was called at runtime.
|
|
|
|
|
|
=== Noncompliant code example
|
|
|
|
[source,php]
|
|
----
|
|
<?php
|
|
|
|
class Toy {
|
|
|
|
public static function status() {
|
|
self::getStatus(); // Noncompliant; will always print "Sticks are fun!" even when called from a subclass which overrides this method;
|
|
}
|
|
|
|
protected static function getStatus() {
|
|
echo "Sticks are fun!";
|
|
}
|
|
}
|
|
|
|
class Ball extends Toy {
|
|
|
|
protected static function getStatus() { // Doesn't actually get called
|
|
echo "Balls are fun!";
|
|
}
|
|
}
|
|
|
|
$myBall = new Ball();
|
|
$myBall::status(); // Prints "Sticks are fun!"
|
|
----
|
|
|
|
|
|
=== Compliant solution
|
|
|
|
[source,php]
|
|
----
|
|
<?php
|
|
|
|
class Toy {
|
|
|
|
public static function status() {
|
|
static::getStatus(); // Compliant
|
|
}
|
|
|
|
protected static function getStatus() {
|
|
echo "Sticks are fun!";
|
|
}
|
|
}
|
|
|
|
class Ball extends Toy {
|
|
|
|
protected static function getStatus() {
|
|
echo "Balls are fun!";
|
|
}
|
|
}
|
|
|
|
$myBall = new Ball();
|
|
$myBall::status(); // Prints "Balls are fun!"
|
|
----
|
|
|
|
|
|
=== Exceptions
|
|
|
|
No issue is raised when ``++self++`` is used on a constant field, a private field or a private method.
|
|
|
|
[source,php]
|
|
----
|
|
class A
|
|
{
|
|
private static $somevar = "hello";
|
|
const CONSTANT = 42;
|
|
|
|
private static function foo()
|
|
{
|
|
$var = self::$somevar . self::CONSTANT; // Should be OK
|
|
self::foo(); // Should be OK
|
|
}
|
|
}
|
|
----
|
|
|
|
|
|
ifdef::env-github,rspecator-view[]
|
|
|
|
'''
|
|
== Implementation Specification
|
|
(visible only on this page)
|
|
|
|
=== Message
|
|
|
|
Use "static" keyword instead of "self".
|
|
|
|
|
|
'''
|
|
== Comments And Links
|
|
(visible only on this page)
|
|
|
|
=== on 12 Oct 2014, 17:00:01 Freddy Mallet wrote:
|
|
@Ann, when discovering this rule it was not obvious for me to understand if there was or not a difference between self:: or static:: prefixes to access static functions of fields.
|
|
|
|
|
|
If my understanding is correct, there is no difference but obviously it's better to use static:: to prevent any misunderstanding.
|
|
|
|
|
|
If this is the case, I would associate this rule to the SQALE characteristic Maintainability > Understandability and to the tag pitfal
|
|
|
|
=== on 14 Oct 2014, 14:43:05 Ann Campbell wrote:
|
|
\[~freddy.mallet] I disagree about SQALE - the point of the rule is that when you use ``++self::++`` you're going to get the superclass' version, not the override - i.e. you won't get what you think you will.
|
|
|
|
=== on 21 Oct 2014, 20:29:24 Ann Campbell wrote:
|
|
\[~linda.martin] LGTM
|
|
|
|
endif::env-github,rspecator-view[]
|