问题
I know there is a difference between static::
and self::
like in this example ( from https://stackoverflow.com/a/13613718/2342518 )
<?php
class One
{
const TEST = "test1";
function test() { echo static::TEST; }
}
class Two extends One
{
const TEST = "test2";
}
$c = new Two();
$c->test();
Which returns test2 when static::TEST
is used and test1 when self::TEST
is used.
But it also returns test2 when $this::TEST
is used.
static::TEST
can be used inside a static method, whereas $this::TEST
requires an instance before being used (so non-usable in static methods).
But if one cannot use $this::
in static methods, static::
can be used in non-static methods (like in the example).
So, what is the difference between static:: and $this:: in a non static method?
Optional complete test
<?php
abstract class AOne
{
const TEST = "test1";
abstract public function test();
}
class OneStatic extends AOne
{
public function test()
{
return static::TEST;
}
}
class TwoStatic extends OneStatic
{
const TEST = "test2";
}
class OneSelf extends AOne
{
public function test()
{
return self::TEST;
}
}
class TwoSelf extends OneSelf
{
const TEST = "test2";
}
class OneThis extends AOne
{
public function test()
{
return $this::TEST;
}
}
class TwoThis extends OneThis
{
const TEST = "test2";
}
$objects = array(
'one, static::' => new OneStatic(),
'two, static::' => new TwoStatic(),
'one, self::' => new OneSelf(),
'two, self::' => new TwoSelf(),
'one, $this::' => new OneThis(),
'two, $this::' => new TwoThis(),
);
$results = array();
foreach ($objects as $name=>$object)
$results[$name] = $object->test();
var_dump($results);
?>
Which yields
- 'one, static::' => 'test1'
- 'two, static::' => 'test2'
- 'one, self::' => 'test1'
- 'two, self::' => 'test1'
- 'one, $this::' => 'test1'
- 'two, $this::' => 'test2'
So self refers to the class where the method is defined, but there's no difference between $this::
and static::
in these non static methods.
回答1:
There are three cases when you CAN'T use $this::
over static::
1. In static methods
public static function test() {
return $this::MY_CONST;
}
Output:
Fatal error: Uncaught Error: Using $this when not in object context
2. In none-static methods which get called in none-object context
class A {
const MY_CONST = 33;
public function test() {
return $this::MY_CONST;
}
}
echo A::test(); // test method here is called without instantiating class A
Output:
Fatal error: Uncaught Error: Using $this when not in object context
3. When using the special ::class
keyword
class A {
public function test() {
return $this::class;
}
}
$a = new A;
echo $a->test();
Output:
Fatal error: Dynamic class names are not allowed in compile-time
Note: in all the three cases static::
will work
For the last case PHP Documentation states that:
Note:
The class name resolution using ::class is a compile time transformation. That means at the time the class name string is created no autoloading has happened yet. As a consequence, class names are expanded even if the class does not exist. No error is issued in that case.
So you can't use $this::class
because you can't reference to non-existent classes
回答2:
There really isn't one. The ::
functionality has been expanded over time, so that the left hand side doesn't need to be a class literal but may also be an object instance or string variable with a class name. Sometime around the same time late static binding was introduced with the static
keyword. As you said, $this
can't be used in static methods, so static
is the obvious and only choice here for late static binding.
In an object instance however you could use static::
to refer to the late-static bound class, which will be the class of the current object instance. Or you could use $this::
as a side effect of being able to use an object instance as shorthand for <class of this object $var>::
. The end result is the same, it's simply functionality which happens to overlap in this particular point. The internal workings are somewhat different, but I can't think of a case where there would ever be any difference.
Just to complete the Venn diagram:
Only static
can do this:
public static function foo() {
static::FOO;
}
Only $var::
can do this:
$obj = new Foo;
$obj::FOO;
Both can do this:
public function foo() {
static::FOO;
$this::FOO;
}
来源:https://stackoverflow.com/questions/24476194/difference-between-static-and-this