新自我与新静态


513

我正在将PHP 5.3库转换为可在PHP 5.2上使用。阻碍我前进的主要因素是使用后期静态绑定,例如return new static($options);,如果将其转换为,return new self($options)将得到相同的结果吗?

new self和之间有什么区别new static

Answers:


888

我会得到相同的结果吗?

并不是的。不过,我不知道针对PHP 5.2的解决方法。

new self和之间有什么区别new static

self指的new是实际写入关键字的同一类。

static在PHP 5.3的最新静态绑定中,指的是您在层次结构上调用方法的任何类。

在以下示例中,B从继承两个方法A。该self调用必然会A因为它在定义A的实现第一种方法的,而static必然要调用的类(见get_called_class())。

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A

说得通。我认为最好的选择是将类名传递给使用后期静态绑定的函数,然后返回新的$ className($ options);。
麦克

12
您不必“传递”类名,您始终可以这样做get_called_class(),它实际上与相同__CLASS__,但与LSB兼容。
shadowhand 2011年

7
<PHP5.3中不存在get_drawn_class。因此,如果要在PHP5.2中获取实例化对象的类名,则在尝试将库从PHP 5.3转换为PHP 5.2时,此功能无济于事
txwikinger 2011年

2
称为self :: theFunction()的函数的行为类似于“我将在我实际所属的类的上下文中执行”。并且称为static :: theFunction()的函数的行为类似于“我将在外界已实际调用的类的上下文中执行”。(假设继承方案)。谢谢
Shubhranshu

2
在我的脑海中,我只是采取直觉主义的观点,而相反。您可能会基于命名来思考,self会返回自己,并static会返回一些无法覆盖的内容……但是,瞧,这是相反的。PHP的命名,约定和整体样式给我留下了深刻的印象。-_-
ahnbizcad '19

23

如果此代码的方法不是静态的,则可以使用来解决5.2 get_class($this)

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

结果:

string(1) "B"
string(1) "B"

17
如果该方法不是静态的,则后期的静态绑定将变得完全不相关。
BoltClock

1
例如,您可以在“复制”方法中使用它,而无需使用即可复制对象clone,而只需重新创建并设置属性即可。$copy = new static(); $copy->set($this->get()); return $copy;
MariusBalčytis2012年

9
@BoltClock当然不是吗?如果要从子类的实例方法中调用重写的静态方法,则对的选择self::static::将影响是否使用该静态方法的基类或子类的版本。在没有任何理由认为这种情况固有地表明不良做法的情况下(我看不出为什么应该这样做),因此在非静态方法中选择self::和之间的static::相关性与在静态方法中一样重要。静态方法。我是否误解了您的评论,还是我们一个人错了?
Mark Amery 2014年

4
@马克·阿默里:嗯,我没想到。你是绝对正确的。我以为在所讨论的实例方法中不会调用任何静态方法,但是根据您的示例,我可以看到这将是一个非常幼稚的假设。
BoltClock


7

除了其他人的答案:

static ::将使用运行时信息进行计算。

这意味着您不能static::在类属性中使用,因为属性值:

必须能够在编译时进行评估,并且不能依赖于运行时信息。

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

使用 self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

请注意,我编写的代码中的致命错误注释没有指出错误发生的位置,该错误发生在对象被实例化为注释中提到的@Grapestain之前


4
请注意,错误是在第2行引发的public $name = static::class;,而不是在第7 行引发的,如示例所示。该错误显示:“ static :: class无法用于编译时类名称解析”,这表明问题不在您尝试访问$ name字段的位置,而是在PHP类的编译之前。在第一个示例中,不会达到第7行(或第6行)。
sbnc.eu

@Grapestain我在示例中所做的评论是显示最终结果,而不是指示错误实际发生的位置。但是无论如何,谢谢你指出这一点。
下雨

是的,我并不是要批评,只是澄清了让我困惑的第一件事,希望它可以对其他人有所帮助。反正很有帮助的例子!
sbnc.eu
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.