PHP魔术方法在各种范围内

时间:2017-11-05 05:08:01

标签: php oop scope magic-methods

我一直在阅读PHP magic methods,并试图更好地理解它们。从PHP手册中可以看出:

  

在与尚未声明或在当前作用域中不可见的属性或方法交互时,将调用重载方法。

我已经阅读了“不visible”的含义:

  

可以通过在声明前加上关键字public,protected或private来定义属性,方法或(从PHP 7.1.0开始)常量的可见性。

请考虑下面的课程:

<?php
    class MyClass{
        private $x = 1;
        protected $y = 2;
        public $z = 3;

        public __construct(){}

        function __get($name){
           switch(true){
             case ($name == 'x'):
                 return 4;
             case ($name == 'y'):
                 return 5;
             case ($name == 'z'):
                 return 6;
             case ($name == 'w'):
                 return 0;
           }
        }

        function sum(){
            return $this->x + $this->y + $this->z;
        }

    }
?>

因此,考虑到上面关于“可见”和“范围”的片段,在什么情况下调用__get魔法,什么时候不调用?

如果我实例化一个新对象:$myclass = new MyClass()$myclass->sum()会返回615还是别的?

如果我致电$myclass->x$myclass->y$myclass->z,结果将是453,因为{{ 1}}和x在技术上不是“可见的”?

我假设调用y将返回$myclass->w而不考虑范围,因为它从未被定义为类的属性,是吗?

2 个答案:

答案 0 :(得分:1)

  

因此,考虑到上面关于“可见”和“范围”的片段,在什么情况下调用__get魔法,什么时候不调用?

当访问对象上不存在的属性时,或者从无法访问属性的范围访问属性时,将调用__get方法。例如,$obj->foo将始终触发__get,而$obj->x会在从课堂外调用时触发__get

  

如果我实例化一个新对象:$myclass = new MyClass()$myclass->sum()会返回6或15或其他内容吗?

它将返回6(1 + 2 + 3)。 $this->x->y->z都可以在课程中访问,因此此处不会触发__get方法。

  

如果我拨打$myclass->x$myclass->y$myclass->z,结果会是4,5和3,因为x和y在技术上并非“可见”,会怎样?

正确。

  

我假设调用$myclass->w将返回0而不考虑范围,因为它从未被定义为类的属性,是吗?

正确,只要您没有明确地为$myclass->w分配值。

答案 1 :(得分:1)

class MyClass {
    private $x = 1;
    protected $y = 2;
    public $z = 3;
    // ...
}

MyClass类的代码中,所有实例属性($x$y$z)都是可见的。 sum()函数会看到它们,当它使用它们时,无需调用__get()

如果代码尝试访问同一类的另一个对象的protectedprivate属性,也会发生这种情况。例如:

class MyClass {
    private $x = 1;
    protected $y = 2;
    public $z = 3;

    public function copyFrom(MyClass $that) {
        $this->x = $that->x;
        $this->y = $that->y;
        $this->z = $that->z;
    }
}

$a = new MyClass();
$b = new MyClass();
$b->copyFrom($a);

copyFrom()方法可以访问$that对象的所有属性(因为它与$this具有相同的类)并且不会调用__get()

但是对于这段代码:

$a = new MyClass();
echo($a->x + $a->y + $a->z);

魔术方法__get()被调用两次,适用于$a->x$a->y,因为这些属性在MyClass类之外的代码中不可见。

作为一般规则,如果类没有定义__get()方法,当访问不可见的属性进行读取时,解释器会触发致命错误:

  

PHP致命错误:未捕获错误:无法访问私有属性MyClass :: $ x

__get()的存在可以抑制错误。而是调用__get(),并使用它返回的值。如果__get()没有返回值(无论为什么),则使用NULL代替(这是函数的标准PHP行为)。