0

假设我们有这个代码:

class SomeClass{

    private $somePrivateField;


    public function __get($name){
        $function = "get".ucfirst($name);
        return $function;
    }

     public function __set($name,$value){
        $function = "set".ucfirst($name);
        return $function($value);
    }

    public function __call($name, $arguments) {
        //if function being called is getSomething
        //getThat private/protected field if exists and return
        //if not raise exception

        // similar for setSomething...
    }

}

这是一些教程的一段话:

__get() 方法接受一个参数,该参数表示正在设置的属性的名称。在 $obj->property 的情况下,参数将是属性。

然后我们的 __get() 方法将其转换为 getProperty,它与我们在 __call() 方法中定义的模式相匹配。这意味着$obj->property会先尝试设置一个同名的公共属性,然后去__get(),然后尝试调用公共方法setProperty(),然后去__call(),最后设置受保护的 $_property。

所以当我在代码中的某个地方说

$obj->property

我可以理解它首先尝试访问公共字段。为什么它首先进入 __get() ?为什么不 __set() ?那为什么会去 __set() 呢?

有人可以解释一下吗?谢谢...

4

1 回答 1

1
  • __get()只会返回一个包含可能不存在的函数名称的字符串。
  • __set()实际上调用了它构造名称的函数,但我无法确定原因,因为......
  • __call()似乎必须确定它调用的函数实际上是“setter”还是“getter”函数,这__get()首先是重点__set()
  • $obj->property是一段毫无意义的代码片段,实际上它自己并没有做任何事情。
// assuming $obj->property is declared as private, or does not exist in the class.

$var = $obj->property; // invokes __get('property')

$obj->property = $var; // invokes __set('property', $var)

$obj->someFunction($var1, $var2, ...);
// invokes __call('someFunction', array($var1, $var2, ...)), but only if
// the specified function is private, or otherwise does not exist.

重写示例代码以使其具有某种意义:

class SomeClass{

    private $somePrivateField;

    public function __get($name){
        if( isset($this->$name) ) {
            return $this->$name;
        } else {
            Throw new Exception("Object property $name does not exist.");
        }
    }

     public function __set($name,$value){
        if( isset($this->$name) ) {
            $this->$name = $value;
        } else {
            Throw new Exception("Object property $name does not exist.");
        }
    }
}
$obj = new SomeClass();
$obj->somePrivateField = $var; // uses __set()
$var = $obj->somePrivateField; // uses __get()

__call()很少需要使用all,对于给定的示例当然不是。

或者,如果您希望能够设置/获取私有/公共属性而无需先显式声明它们:

class SomeClass{

    private $properties = array();

    public function __get($name){
        if( isset($this->properties['name']) ) {
            return $this->properties['name'];
        } else {
            Throw new Exception("Object property $name does not exist.");
        }
    }

     public function __set($name,$value){
        $this->properties[$name] = $value;
    }

    // it's also a good idea to define __isset() and __unset() in this case as well
    public function __isset($name) {
        return isset($this->properties['name']);
    }

    public function __unset($name) {
        return unset($this->properties['name']);
    }
}
于 2013-01-30T19:56:07.047 回答