Мне нужно создать неизменяемый класс, который является просто контейнером поля члена. Я хочу, чтобы его поля были созданы один раз в своем конструкторе (значения должны указываться как параметры для конструктора). Я хочу, чтобы поля были общедоступными, но неизменными. Я мог бы сделать это с помощью Java, используя ключевое слово final
перед каждым полем. Как это делается в PHP?
PHP: неизменные поля публичных пользователей
Ответ 1
Вы должны использовать магические методы __set
и __get
и объявить это свойство как защищенное или личное:
/**
* @property-read string $value
*/
class Example
{
private $value;
public function __construct()
{
$this->value = "test";
}
public function __get($key)
{
if (property_exists($this, $key)) {
return $this->{$key};
} else {
return null; // or throw an exception
}
}
public function __set($key, $value)
{
return; // or throw an exception
}
}
Пример:
$example = new Example();
var_dump($example->value);
$example->value = "invalid";
var_dump($example->value);
string(4) "test"
string(4) "test"
@property-read
должен помочь вашей IDE признать существование этого магического свойства.
Ответ 2
Вы можете использовать магический метод __set()
и вызывать исключение, когда кто-то пытается напрямую установить свойство.
class ClassName {
public function __set($key, $value) {
throw new Exception('Can't modify property directly.');
}
}
Однако это предотвратит модификацию свойств независимо от того, являются ли они общедоступными или нет.
Ответ 3
чтобы вы могли сделать лучше - если у вас есть количество полей в динамике
class ClassName {
private $fields = array();
// use class : $cl = new ClassName(array('f'=>2,'field_4'=>5,''12));
// echo $cl->field_4; echo $cl->f;
public function __construct($data= array())
{
if (!is_array($data) || !count($data)) throw new Exception('Not enough args')
foreach ($data as $key=>$val)
{
if (is_numeric($key))
$this->fields['field_'.$key] = $val;
else
$this->fields[$key] = $val;
}
}
/* in this case you can use this class like $cl = new ClassName(12,14,13,15,12); echo $cl->field_1;
public function __construct()
{
$ata = funcs_get_args();
if (!count($data)) throw new Exception('Not enough args')
foreach ($data as $key=>$val)
{
if (is_numeric($key))
$this->fields['field_'.$key] = $val;
else
$this->fields[$key] = $val;
}
}
*/
public function __get($var) {
if (isset($this->fields[$var]))
return $this->fields[$var];
return false;
//or throw new Exception ('Undeclared property');
}
}
Ответ 4
<?php
declare(strict_types=1);
final class Immutable
{
/** @var string */
private $value;
public static function withValue(string $value): self
{
return new self($value);
}
public function __construct(string $value)
{
$this->value = $value;
}
public function value(): string
{
return $this->value;
}
}
// Example of usage:
$immutable = Immutable::withValue("my value");
$immutable->value(); // You can get its value but there is no way to modify it.