简体   繁体   English

为什么使用__set()和__get()方法而不是将属性声明为public

[英]why use __set() & __get() method rather than declare a property as public

I am new to php.I know __set() and __get() create protected property but it behaves like a public property.And properties created by this method are set to PROTECTED.But only difference is that they can be accessed any time from anywhere just like public properties.As i don't have any practical working experience on php,I would like to know why not create a public property instead of taking the trouble of using __get() and __set() ??Also __set() property creates property during runtime. 我是php的新手,我知道__set()和__get()创建了受保护的属性,但它的行为就像一个公共属性,并且此方法创建的属性被设置为PROTECTED。但是唯一的区别是它们可以随时随地访问就像公共属性一样。由于我在php上没有任何实际工作经验,我想知道为什么不创建公共属性而不是麻烦使用__get()和__set()以及 __set()属性在运行时创建属性。 Does it create a problem while tracking all the properties of an object ?? 在跟踪对象的所有属性时会产生问题吗?

class foo {
   protected $another='lol';  //protected property


    public function __get($name) {


        return $this->$name;
    }

    public function __set($name, $value) {


        $this->$name = $value;
    }
}

class bar extends foo{     // inherits from foo

    public function __get($name){   //__get() method for bar class
        return $this->$name;       //
    }
}

$foo = new foo();

$foo->bar = 'test';

echo $foo->another;  //echos protected property from parent class

echo '</br>';

$bar=new bar();

echo $bar->another;   //  echos inherited private property from parent class

var_dump($foo);

It's all to do with encapsulating the data in a class so that the outer world cannot directly modify the values of this data. 这与将数据封装在一个类中有关,以至于外部世界无法直接修改此数据的值。 If you're repeatedly setting the values of a variable from outside class you might want to think about if the variable you're changing should actually be in its current class. 如果要从外部类重复设置变量的值,则可能要考虑要更改的变量是否实际上应在其当前类中。 You can also have more control over the variable's accessibility. 您还可以更好地控制变量的可访问性。 For example, just providing a get() method and preventing yourself from setting a value when you shouldn't really be doing it. 例如,仅提供get()方法并防止您在本不应该这样做的情况下设置值。 Having a method to set the value of something also provides a very handy place for validation rather than checking values outside the class where you may forget from time to time. 拥有一种设置某些事物的值的方法也为验证提供了一个非常方便的地方,而不是检查类外的值,而您有时会忘记这些值。 Also protected properties are different from public properties as they can't be accessed anywhere, just in the variable's own class or classes inherited from the class the variable is in. 受保护的属性也不同于公共属性,因为它们无法在任何地方访问,只能在变量自己的类中或从变量所在的类继承的类中访问。

There's very little reason to use __get, __set (or __call for that matter) in a way where the actual data structure is fixed (eg you have a fixed set of members and only access them through those methods. 几乎没有理由以固定实际数据结构的方式使用__get,__ set(或__call)(例如,您有一组固定的成员,并且只能通过这些方法访问它们)。

The advantage of these methods lies in situations where you don't actually have a fixed structure. 这些方法的优点在于您实际上没有固定的结构。 While these situations should usually be avoided there are some situations where this may become handy. 尽管通常应避免这些情况,但在某些情况下可能会变得很方便。

For instance I have a model class for a very lightweight ORM which doesn't require code generation and still features a public interface similar to more complex ActiveRecord style frameworks (i use __call in this and extract the field name from the called method, but __get/__set would work as well). 例如,我有一个非常轻量级的ORM的模型类,该类不需要代码生成,并且仍然具有类似于更复杂的ActiveRecord样式框架的公共接口(我在其中使用__call并从被调用的方法中提取字段名称,但是__get / __ set也可以)。

class User extends AbstractModel {
    protected static $FIELD_LIST = ['id', 'username', 'password'];
}

$foo = new MyModel();
$foo->setId(123);
$foo->setUsername('Foo');
$foo->setPassword('secret');
$foo->setNonExistantField('World!'); // will throw an exception

This allows me to rapidly create a model class where at any point I can decide to write a custom setter method. 这使我可以快速创建一个模型类,在任何时候我都可以决定编写一个自定义setter方法。 eg if I wanted to store that password as a salted hash I could do something like this: 例如,如果我想将该密码存储为盐腌哈希,可以执行以下操作:

class User extends AbstractModel {
    protected static $FIELD_LIST = ['id', 'username', 'password'];

    public function setPassword($password) {
        $salt = magic_salt_function();
        $hash = crypt($password, '$2a$08$' . $salt);
        $this->data['password'] = $hash;
    }
}

The advantage being that I don't have to write getter/setter methods for every field but at any point can. 优点是,我不必为每个字段都编写getter / setter方法,但是在任何时候都可以。 Very handy in rapid prototyping. 快速原型制作非常方便。

Similar techniques can be used for example if you have some data in array from which you want to modify with object syntax. 例如,如果您要使用对象语法修改数组中的某些数据,则可以使用类似的技术。 Using __get/__set allows you to avoid having to go through the array whenever you leave object context back to array context. 使用__get / __ set可以使您避免在每次将对象上下文返回到数组上下文时都必须遍历数组。

class Foo {
    protected $data;

    public function __construct(array $data) {
        $this->data = $data;
    }

    public function __get($key) {
        if(!isset($this->data[$key])) {
            throw new Exception("Unknown member $key");
        }

        return $this->data[$key];
    }

    public function __set($key, $value) {
        if(!isset($this->data[$key])) {
            throw new Exception("Unknown member $key");
        }

        $this->data[$key] = $value;
    }

    public function getData() {
        return $this->data;
    }
}

$data = [
    'bar' => true,
    'braz' => false
];
$foo = new Foo($data);
$foo->bar = false;
$foo->braz = true;
$foo->nope = true; // will throw an exception

In the end overloading in PHP is a tool for a pretty specific task (creating dynamic interfaces). 最后,PHP中的重载是一个用于完成特定任务(创建动态接口)的工具。 If you don't need it, you don't use it. 如果不需要它,就不要使用它。 And when you use it, you should be aware that it has its downsides. 当您使用它时,您应该意识到它有缺点。 After all once you overload you're in charge of validation that normally the interpreter could do for you. 毕竟,一旦您超载,您就将负责通常由解释器为您完成的验证。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么CakePHP在MySQL查询中使用此方法名称而不返回结果? - Why does CakePHP use this method name in a MySQL query rather than return the result? 为什么要使用事件监听器而不是库类,或者根本不使用它 - Why use Event Listeners rather than library class or not use it at all 使用POST而不是GET保护CakePHP中的方法 - Protecting a method in CakePHP using POST rather than GET 在值对象中,为什么要使用特定的属性集和get方法? - In a value object, why use specific property set and get methods? 为什么使用NuSOAP而不是PHP SOAP? 有什么好处? - Why use NuSOAP rather than PHP SOAP? Any benefits? 我为什么要使用strtolower()而不是mb_strtolower()? - Why should I use strtolower() rather than mb_strtolower()? 关于for(),为什么要使用i ++而不是++ i? - In regards to for(), why use i++ rather than ++i? 为什么在此示例中Facebook为什么使用Javascript而不是HTTP Header? - Why did Facebook use Javascript rather than an HTTP Header in this Example? 公共方法无法访问的公共财产 - Public property inaccessible in public method 何时使用`public static function createInstance()`而不是通常的构造函数来实现类? - When to use `public static function createInstance()` rather than a usual constructor to instanciate a class?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM