【问题标题】:Declaring protected variables in methods在方法中声明受保护的变量
【发布时间】:2011-03-23 16:23:50
【问题描述】:

我环顾四周,似乎找不到这个问题的答案。

基本上我使用 _call 方法来动态生成 get 和 set 方法,但是在声明变量时 PHP 的默认值是公共的。有没有将一个类中的变量声明为受保护的?

function __call($method, $arguments) {
    $prefix = strtolower(substr($method, 0, 3));
    $property = strtolower(substr($method, 3));

    if (empty($prefix) || empty($property)) {
        return;
    }

    if ($prefix == "get" && isset($this->$property)) {
        return $this->$property;
    }

    if ($prefix == "set") {

        $this->$property = $arguments[0];
    }
}

【问题讨论】:

标签: php oop class visibility


【解决方案1】:

一种选择是拥有一个受保护的数组,并通过你的魔法设置器在该数组中设置一个元素。

class MyClass {
    protected $_myProperties = array();

    public function __get($name) {
        if (isset($this->_myProperties[$name])) {
            return $this->_myProperties[$name];
        } else {
            return null;
        }
    }

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

    public function __isset($name) {
        return isset($this->_myProperties[$name]);
    }
}

【讨论】:

  • 谢谢,完成了。工作完美,但保持调用方法习惯使用 $class->getSomething();
【解决方案2】:

首先,如果没有设置前缀或属性变量,我强烈建议不要returning。这将使调试变得非常困难。而是将return; 替换为throw new BadMethodCallException('Method Does Not Exist: '.$method);

其次,这不是破坏了受保护变量的意义吗?它允许在没有任何验证的情况下读取和写入所有属性。如果您要这样做,不妨将它们公开。

我个人认为$foo->bar = 'baz';$foo->setBar('baz'); 更具可读性。不是因为它“更容易”理解,而是因为第二个是不必要的冗长。

就个人而言,我建议做一个__get__set,并添加验证。保护变量的全部意义在于信任(以便您可以信任设置)。当然,您可以使用反射或子类来更改它们,但我通常假设如果有人走那么远,如果他们弄乱了一个变量,他们应该有任何意想不到的后果。

请记住,如果您使用任何类型的魔术方法,如果您希望 IDE 向您提示方法/变量,则需要添加文档元素...

编辑:

别忘了,如果你声明了__get/__set 方法,你可以在子类中重写它们。所以如果孩子声明了新的变量,你可以在那里处理,然后调用parent::__get来处理默认变量。因此,不要使用数组,以便您可以为所有孩子提供一种方法。为你认识的成员做验证,让你的孩子自己处理验证...

【讨论】:

  • +1 不同意 $foo->setBar('baz');与 $foo->bar = 'baz'; 相比,不必要地冗长。因为 getter 和 setter 方法总是允许对设置属性进行验证,而非私有属性总是可以绕过任何验证来设置...但是这里有很多非常有用的 sn-ps 信息
  • 这只是我可能需要添加到类中的任何变量的后备方法。一般来说,我总是在必要时对受保护的变量使用 get 和 set 方法。我完全理解调试的困难,并且只会谨慎地使用这种方法来实现 DRY。
  • 嗯,我确实不时使用getBar() 语法,但我尽量不使用,除非它真的有意义。我只是不喜欢在一个类中有 50 个方法只是为了获取/设置成员变量的混乱......大多数时候它根本没有必要(但并非总是如此)......
【解决方案3】:

是否可以将类中的变量声明为受保护?

好像不是这样。您可以使用Reflectionchange the accessibility of properties,但似乎只能有效地用于公开以前未公开的内容。

您可能希望考虑将自动生成的属性存储在具有适当可见性的数组中。

(还有__get__set,但它们可能不符合您的需求。它们只会在属性丢失不可访问时被调用。能够接触受保护的类属性会绕过它们。)

【讨论】:

  • 是的,我同意您的第二段...将这些生成的“属性”存储在关联数组中。然后,关联数组可以成为您的类的受保护属性。为了使用__get__set 我认为你需要这样做。
  • 我不同意。这违背了成员变量的观点。当类将存储未知变量(例如注册表类或类似的东西)时,我使用关联数组。但是,当您拥有一组有限的已知变量时,为什么不使用成员变量来实现它们的设计目的呢?
  • 我只能从这个问题中想象,他正在做某种古怪的继承和/或可见性魔术。除非上面发布的代码不完整,否则我看不到对属性进行任何转换...
猜你喜欢
  • 2019-11-21
  • 2017-06-05
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
  • 2014-01-23
  • 2011-08-18
  • 1970-01-01
相关资源
最近更新 更多