【问题标题】:PHP magic methods in various scopes各种范围内的 PHP 魔术方法
【发布时间】:2017-11-05 05:08:00
【问题描述】:

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

重载方法在与尚未声明或在当前范围内不可见的属性或方法交互时被调用。

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

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

所以考虑下面的类:

<?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;
        }

    }
?>

那么考虑到上面关于“可见”和“范围”的 sn-ps,__get 魔术方法会在什么情况下被调用,什么时候不会?

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

如果我调用$myclass-&gt;x$myclass-&gt;y$myclass-&gt;z,结果会是453,因为xy 在技术上不“可见”?

我假设调用$myclass-&gt;w 将返回0 而不管范围如何,因为它一开始就没有被定义为类的属性,对吗?

【问题讨论】:

  • “公共函数 __construct(){}”。缺少 switch 语句的结束 }。而且用switch ($name) { case 'x': return 4; case 'y': return 5; } 更清楚
  • 这里有一个免费提示:不要使用魔法吸气剂和二传手。

标签: php oop scope magic-methods


【解决方案1】:

那么考虑到上面关于“可见”和“范围”的 sn-ps,__get 魔术方法会在什么情况下被调用,什么时候不会?

__get 方法将在访问对象上不存在的属性时调用,或者从无法访问的范围内访问属性时调用。例如,$obj-&gt;foo 将始终触发__get,而$obj-&gt;x 在从类外部调用时将触发__get

如果我实例化一个新对象:$myclass = new MyClass()$myclass-&gt;sum() 会返回 6 或 15 还是其他值?

它将返回 6 (1 + 2 + 3)。 $this-&gt;x-&gt;y-&gt;z都可以在类内部访问,所以这里不会触发__get方法。

如果我调用$myclass-&gt;x$myclass-&gt;y$myclass-&gt;z,结果会是 4、5 和 3,因为 x 和 y 在技术上是不“可见的”吗?

正确。

我假设调用 $myclass-&gt;w 将返回 0 而不管范围如何,因为它从来没有被定义为类的属性,对吗?

正确,只要您没有明确地为 $myclass-&gt;w 赋值。

【讨论】:

    【解决方案2】:
    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-&gt;x$a-&gt;y,因为这些属性在MyClass 类之外的代码中是不可见的。


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

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

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

    【讨论】:

      猜你喜欢
      • 2015-09-13
      • 1970-01-01
      • 2023-03-14
      • 2010-10-27
      • 1970-01-01
      • 1970-01-01
      • 2011-06-10
      • 2010-12-26
      • 1970-01-01
      相关资源
      最近更新 更多