静态::和$ this之间的区别::

时间:2014-06-29 12:48:09

标签: php static this self

我知道此示例中的static::self::之间存在差异(来自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();

使用static::TEST时返回 test2 ,使用self::TEST时返回 test1 。 但是当使用$this::TEST时,它也会返回 test2

static::TEST可以在静态方法中使用,而$this::TEST在使用之前需要一个实例(因此在静态方法中不可用)。

但是如果在静态方法中不能使用$this::static::可以在非静态方法中使用(如示例中所示)。

那么,静态方法中static ::和this ::之间的区别是什么?


可选的完整测试

<?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);
?>

哪个收益

  • &#39; one,static ::&#39; =&GT; &#39; TEST1&#39;
  • &#39; two,static ::&#39; =&GT; &#39; TEST2&#39;
  • &#39; one,self ::&#39; =&GT; &#39; TEST1&#39;
  • &#39;二,自我::&#39; =&GT; &#39; TEST1&#39;
  • &#39; one,$ this ::&#39; =&GT; &#39; TEST1&#39;
  • &#39;二,$ this ::&#39; =&GT; &#39; TEST2&#39;

因此,self指的是定义方法的类,但在这些非静态方法中$this::static::之间没有区别。

2 个答案:

答案 0 :(得分:2)

真的没有一个。 ::功能随着时间的推移而扩展,因此左侧不需要是类文字,但也可以是具有类名的对象实例或字符串变量。大约在同一时间,使用static关键字引入了后期静态绑定。正如您所说,$this不能在静态方法中使用,因此static是后期静态绑定的明显唯一选择。

在对象实例中,您可以使用static::来引用后期静态绑定类,它将是当前对象实例的类。或者您可以使用$this::作为能够使用对象实例作为<class of this object $var>::的简写的副作用。最终结果是相同的,它只是在这个特定点上恰好重叠的功能。内部运作有所不同,但我想不出有任何差异的情况。

完成维恩图:

只有static可以执行此操作:

public static function foo() {
    static::FOO;
}

只有$var::可以执行此操作:

$obj = new Foo;
$obj::FOO;

两者都可以做到:

public function foo() {
    static::FOO;
    $this::FOO;
}

答案 1 :(得分:2)

在三种情况下,您不能使用$this::而不是static::

1。在静态方法中

public static function test() {
    return $this::MY_CONST;
}

输出:

  

致命错误:未捕获错误:在对象上下文中不使用$ this

2。在非对象上下文中调用的非静态方法中

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

输出:

  

致命错误:未捕获错误:在对象上下文中不使用$ this

3。使用特殊的::class关键字

class A {
    public function test() {
        return $this::class;
    }
}

$a = new A;
echo $a->test();

输出:

  

致命错误:在编译时不允许动态类名

注意:在所有三种情况下,static::都可以工作


对于最后一种情况 PHP Documentation指出:

  

注意:

     

使用:: class的类名称解析是编译时间   转型。这意味着当时的类名字符串是   创建没有自动加载发生。结果,类名   即使该类不存在,也会被扩展。没有发出错误   这种情况。

因此您不能使用$this::class,因为您不能引用不存在的类