静态调用非静态方法

<?php
class myClass
{
    private $name = "myClass";
 
    public function echoName(){
        echo $this->name;
    }
 
    public function getName(){
        $this->echoName();
    }
}
 
class newClass
{
    private $name = "newClass";
 
    public function echoName(){
        echo $this->name;
    }
 
    public function test() {
        myClass::getName();
        echo "\n";
    }
}
 
$app = new newClass();
$app->test();

 这个代码的最终调用结果是什么呢?(运行环境PHP 5.3.10 )

返回PHP Strict Standards Error。熟悉php的人应该知道,Strict Error是php的编码标准化警告,一般是由于php为了保持向前兼容而报出的错误。那这么说,非静态函数的静态调用在php5.3之前的某个版本是允 许的,只是在后面的版本是不被建议使用!!

如果你现在将Strict Error在error_reporting中注释掉,返回结果就变成了newClass!!

这个是为什么呢?按照我们的理解,即使调用的是myClass的getName()方法,返回的也应该是“myClass”,为什么会是“newClass”呢?

什么是静态调用?并不是说有::就是静态调用,而是看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对象, 那么这个还算静态调用么?

出现这样的问题是因为,在一个有calling scope的上下文中采用”静态的形式”调用了一个类的非静态方法所致.

    <?php
     class A {
        public function __construct() {
        }
     }
      class B extends A {
        public function __construct() {
            parent::__construct();
       }
       }

 当我们调用父类的构造函数的时候, 我们是有意的要把当前的scope传递给父类的构造函数作为calling scope的(这里的parent::_construct()是子类将calling scope转化为父类A的calling scope。这个并不是静态调用)

静态调用是没有calling scope的,非静态调用this指向的对象就是calling scope。

Calling scope是当每一句调用的时候被传递的。

这个时候由于没有使用parent这样的关键字,也没有对this重新赋值, calling scope任然是app,就是说这个时候,所有出现的this指针指向的都是app的。

echo $this->name; 自然就是调用calling scope的name属性了。

 

posted @ 2016-01-22 11:13  坠落鱼  阅读(817)  评论(0编辑  收藏  举报