php点__get()和__set()魔术

时间:2009-10-22 21:42:48

标签: php oop

PHP 5引入了魔术方法__get()和__set()。根据我的理解,这是必须编写每个成员的getter和setter的捷径;

 <?php
class Person {
    private $firstname;
    private $lastname;

    function __set($var, $name) {
        $this->$var = $name;
    }

    function __get($var) {
        return $this->$var;
    }
}

$person = new Person();
$person->firstname = "Tom";
$person->lastname = "Brady";


echo $person->firstname . " " . $person->lastname;

// print: Tom Brady
?>

我的问题是,这就像将成员变量公之于众。

class Person {
    public $firstname;
    public $lastname;
}

这不符合OOP原则吗?那有什么意义呢?

3 个答案:

答案 0 :(得分:3)

在你的例子中,将它们公开是一回事。但是,你的__set&amp; __get函数不必处理所有变量。 (可能使用switch语句来决定要处理哪个。)此外,您可以对__set的参数执行数据验证,或者计算根本不存在的__get的返回值。

注意到您在代码中使用了$ this-&gt; var而不是$ this-&gt; $ var(这是我认为您希望代码正常工作的原因)

答案 1 :(得分:2)

需要理解的是,“OOP原则”不是一成不变的。 它们更像是经验法则。

因此,例如在python中,所有成员变量都是公共的。没有真正的私人变量。

在Smalltalk中,所有变量都是私有的,如果要提供对需要getter的变量的访问,则没有公共变量。事实上,这里是吸气者和制定者的实践所在。

因此,php中的神奇getter和setter在很多情况下都很有用。 例如:

  • ORMappers
  • 构建要发送到外部API的对象时
  • 当您想要识别访问变量的人时。

现在,如果你想保留私有变量,仍然使用魔法getter和setter 再次针对您的应用程序的特定情况,您可以修改您的代码 对私有变量使用'_'下划线约定。

<?php
class Person {
    private $_firstname;
    private $_lastname;

    function __set($name, $value) {
        if (!strpos('_', $name) === 0) {
            $this->$name = $value;
        } else {
            throw new Exception ("trying to assign a private variable");
        }
    }

    function __get($name) {
        if (!strpos('_', $name) === 0) {
            retrun $this->$name;
        } else {
            throw new Exception ("trying to read a private variable");
        }
    }
}

?>

答案 2 :(得分:0)

首先,您的示例不起作用,因为您正在访问$this->var

第二:是的,添加魔术套装和吸气剂就像添加制定者和吸气剂一样。只是魔术。

__set和__get有用:如果你正在构建一个像ORM这样的库,它可能会派上用场。此外,它可以用作穷人的属性:如果你最初公开了一个字段,你现在可以在__set和__get中添加行为,就像它总是在那里一样(例如,验证)。