Bun Wong's Blog

专注于 Web 应用程序开发

Magic Methods of PHP (1)

今天看了一下关于 PHP 的类内魔术函数,发现以前有不少地方是没有注意到的,算是系统地补习一下:

关于 Overloading

以前忽略了 inaccessible members 和 inaccessible methods,以下是引用自文档的部分:

__set() is run when writing data to inaccessible members.
__get() is utilized for reading data from inaccessible members.
__isset() is triggered by calling isset() or empty() on inaccessible members.
__unset() is invoked when unset() is used on inaccessible members.
__call() is triggered when invoking inaccessible methods in an object context.
__callStatic() is triggered when invoking inaccessible methods in a static context.

注意到 inaccessible 在文档里描述的是那些未定义的或者不在作用域内的成员变量或方法,因此:当实例 $class 有一个已存在的声明为 public 的成员变量 $var

public $var 0;

那么当我们调用

$class->var;
$class->var = 1;
isset($class->var);
unset($class->var);

时,将不会调用 __get(), __set(), __isset(), __unset() 而直接操作该成员变量,由此可知道,假设有

class Example1
{
    public function __get($name)
    {
        return $name;
    }
    public function __set($name$value)
    {
        $this->$name = $value;
    }
    public function __isset($name)
    {
        return isset($this->$name);
    }
    public function __unset($name)
    {
        unset($this->$name);
    }
}

则有

$class new Example1();
$class->var;        // 调用 __get('var')
$class->var = 0;    // 调用 __set('var', 0)
$class->var = 1;    // 不调用 __set()
$class->var;        // 不调用 __get()
isset($class->var); // 不调用 __isset()
unset($class->var); // 不调用 __unset()
unset($class->var); // 调用 __unset('var')
isset($class->var); // 调用 __isset('var')

因此我猜想,下面这种方式(官方举出的例子)是否会降低效率呢?因为它所声明的成员一直都是 inaccessible 的,因此会调用 magic methods 而增大了调用的开销,就像 Zend_View 也只是使用了上述 Example1 的方式来赋值给类的(这个验证估计要查看 PHP 源代码才能得到确切的答案)。

class Example2
{
    private $_data;
    
    public function __get($name)
    {
        return $this->_data[$name];
    }
    public function __set($name$value)
    {
        $this->_data[$name] = $value;
    }
    public function __isset($name)
    {
        return isset($this->_data[$name]);
    }
    public function __unset($name)
    {
        unset($this->_data[$name]);
    }
}

总结一下,

成员变量:

  • 在类声明里已声明且为 public,总不调用 magic methods
  • 在类声明里已声明且为 private 或 protected,那么它们的作用域并不在类外,因此每次都会调用 magic methods
  • 在类声明里未声明,每次都会调用 magic methods,当运行时 set 成员变量时,这个变量为 public
  • 若在运行时 unset 成员变量,下一次访问总会调用 magic methods,当重新 set 时,如变量已在类声明里声明过的 (private, protected, public),权限将与声明的权限相同

成员函数:

  • 在类声明里已声明函数的,若为 public,则不调用 __call(),若为 private 或 protected,会产生 Fatal error
  • 在类声明里未声明,总调用 __call()
000000

支持

鸡蛋

路过

雷人

我晕

好帅

留言 (5)

  • test

    February 6th 2009 • 08:41

    test

  • 肘子

    February 6th 2009 • 08:58

    劳务费,劳务费

  • 番仔

    February 9th 2009 • 14:09

    没事再飘一下

  • Your ara so great!

    February 16th 2009 • 15:20

    Your ara so great!

  • Bun Wong

    February 20th 2009 • 12:57

    有时候简单的东西很容易会疏忽掉…

发表留言

Google Analytics

最近一个月访问数:544