__get()和__set()是否意味着泄漏封装?

时间:2014-06-03 16:18:14

标签: php oop

在OO编程中,我们会瞧不起使用魔术方法__get()__set(),这些会导致封装泄漏出类吗?例如:

class User {
    private $username;
    private $password;

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

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

这有效地使private / protected变量public成为可能。

3 个答案:

答案 0 :(得分:5)

您的代码:

class User {
    private $username;
    private $password;

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

    public function __get($name) {
        return $this->$name;
    }
}
在这种情况下,

是完全没必要的。

封装does not mean“一堆吸气剂和二传手”。您可以将其重构为:

class User {
    public $username;
    public $password;
}

就封装而言,它们是等价的。

一般来说,__get__set有一些用途,但是如果你不能这样做,你应该(特别是考虑到它们比正常的方法定义"considerably slower")。

答案 1 :(得分:0)

如果你那样使用它,那么是的。行为将完全相同,您应该只使用公共变量,因为这在PHP中更快。

setter有用的东西是在实际分配值之前检查值:

public function __set($name, $value)
{
    switch($name)
    {
        case 'username':
          if(strlen($value) < 6 || strlen($value) > 30)
            throw new Exception();

          ...
          break;

        case 'password':
          //some security checks
          break;

        default: throw Exception('no property'.$name);
    }

    $this->$name = $value;
}

答案 2 :(得分:0)

这个问题没有严格的是/否答案。相反,有一个解释:

从纯粹的面向对象的角度来看,是的,这是一个漏洞的封装。为什么?考虑一个类具有许多属性的情况,每个属性都有一个getter和一个setter。现在,如果在大型复杂的应用程序中使用此类,在许多地方以及在许多方面,则很难控制对象的状态(属性值),因为它可以在很多方面进行修改/更改位置,通过附件(吸气剂和制定者)。那么,解决方案是什么?嗯,一般来说,更好的设计是通过构造函数构造一个对象。例如,User类可以重新设计为:

class User {
    private username;
    private password;

    // constructor
    public User(name, password) {
        this->username = name;
        this->password = password;
    }

    // other methods
}

在这个新设计中,只有一种方法可以使用构造函数创建User类型的对象。这可以保证以受控方式以已知方式创建对象,因此可以随时了解其行为。

考虑到上面的论点,它不是使封装泄漏的getter,而是setter,因为它们是修饰符;除了构造时间之外,任何时候都可以修改对象1)在构造函数2之外的状态。

总而言之,有些情况下,必须为一个班级提供getter和setter。例如,某些对象关系框架需要这样,因为它们能够修改对象。