PHP的Calling Scope(::调用非静态方法)

今天在群里发现有人说,PHP可以用::调用非静态方法,一致没这么试过,发现了鸟哥的blog写了这个问题的具体解释,就搬过来:

这个问题乍看, 确实很容易让人迷惑, 但实际上, 造成这样的误解的根本原因在于: 在PHP中, 判断静态与否不是靠”::”(PAAMAYIM_NEKUDOTAYIM)符号, 而是靠calling scope.

那么, 什么是calling scope?

在PHP中, 调用一个方法的时候, $this指针指向的对象就是这个方法被调用时刻的calling scope. 对于下面的例子:

<?php

Foo::bar();

?>

在调用bar方法的时候, 处于一个没有calling scope域的上下文中, 所以这个是静态调用.

而对于如下的例子:

<?php

class A {

     public function test() {

         Foo::bar();

     }

 }

$a  = new A();

$a->test();

在调用bar方法的时候, 处于一个$a对象的上下文中, 也就是说, 此时的calling scope是$a对象, 所以这个其实不是静态调用.

为了验证这一个结论, 请看下面的一个实际例子:

<?php

 class Foo {

     public function bar() {

         var_dump($this);

     }

 }

 class A {

     public function test() {

         Foo::bar();

     }

 }

 $a  = new A();

 $a->test();

?>

输出什么呢?

object(A)#1 (0) {

}

在调用bar的时候, 这个看似”静态”调用的调用, $this指针却是被赋值的, 指向的是$a对象, 那么这个还算静态调用么?

我举这个例子是为了说明这个问题, 但大家在实际的应用中, 大家尽量要避免使用”::”来调用一个非静态的方法, PHP也会对于这种调用给出一个Strict 警告:

也许有人会说这个应该算bug吧? 其实不然, 更多的应该是错误使用造成的, 因为你在一个有calling scope的上下文中采用”静态的形式”调用了一个类的非静态方法所致.

那么PHP为什么要这么设计呢? 考虑下面的例子:

<?php

 class A {

    public function __construct() {

    }

 }

 class B extends A {

    public function __construct() {

        parent::__construct();

   }

 }

当我们调用父类的构造函数的时候, 我们是有意的要把当前的scope传递给父类的构造函数作为calling scope的.

你可能感兴趣的:(scope)