зачем использовать __set () & amp; __get (), а не объявлять свойство как public

Я новичок в php. Я знаю, что __set () и __get () создают защищенное свойство, но оно ведет себя как открытое свойство. И свойства, созданные этим методом, имеют значение PROTECTED. Но единственное отличие состоит в том, что к ним можно получить доступ в любое время из любого места так же, как публичные свойства. Поскольку у меня нет практического опыта работы на PHP, я хотел бы знать, почему бы не создать открытое свойство вместо того, чтобы использовать __get () и __set ()??Также свойство __set () создает свойство во время выполнения.Создает ли это проблему при отслеживании всех свойств объекта???

class foo {
protected $another='lol';  //protected propertypublic 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);

0

Решение

Это все связано с инкапсуляцией данных в классе, так что внешний мир не может напрямую изменять значения этих данных. Если вы неоднократно устанавливаете значения переменной из внешнего класса, вы можете подумать о том, должна ли изменяемая переменная находиться в ее текущем классе. Вы также можете лучше контролировать доступность переменной. Например, просто предоставив метод get () и не позволяя себе устанавливать значение, когда вы не должны этого делать. Наличие метода для установки значения чего-либо также предоставляет очень удобное место для проверки, вместо проверки значений вне класса, где вы можете время от времени забывать. Кроме того, защищенные свойства отличаются от общедоступных свойств, поскольку к ним нельзя получить доступ где угодно, только в собственном классе переменной или в классах, унаследованных от класса, в котором находится переменная.

1

Другие решения

Существует очень мало причин использовать __get, __set (или __call в этом отношении) таким образом, чтобы фактическая структура данных была фиксированной (например, у вас есть фиксированный набор членов и доступ к ним только через эти методы.

Преимущество этих методов заключается в ситуациях, когда у вас нет фиксированной структуры. Хотя таких ситуаций обычно следует избегать, в некоторых ситуациях это может оказаться полезным.

Например, у меня есть класс модели для очень легкого 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

Это позволяет мне быстро создать класс модели, в котором в любой момент я могу написать собственный метод установки. например если бы я хотел сохранить этот пароль как соленый хеш, я мог бы сделать что-то вроде этого:

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

Преимущество в том, что мне не нужно писать методы получения / установки для каждого поля, но в любой момент можно. Очень удобно в быстром прототипировании.

Подобные методы можно использовать, например, если у вас есть данные в массиве, которые вы хотите изменить с помощью синтаксиса объекта. Использование __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

В конце концов, перегрузка в PHP — это инструмент для довольно специфической задачи (создание динамических интерфейсов). Если вам это не нужно, вы его не используете. И когда вы используете его, вы должны знать, что у него есть свои недостатки. В конце концов, когда вы перегружены, вы отвечаете за проверку, что обычно переводчик может сделать для вас.

1

По вопросам рекламы [email protected]