我需要创建一个不可变的类,它只是一个成员字段容器。我希望它的字段在其构造函数中实例化一次(值应作为构造函数的参数给出)。我希望这些字段是公开的但不可变的。我可以在每个字段之前使用final
关键字用Java完成它。它是如何在PHP中完成的?
答案 0 :(得分:17)
您应该使用__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确认存在这种魔法属性。
答案 1 :(得分:2)
您可以使用__set()
魔术方法,并在有人试图直接设置属性时抛出异常。
class ClassName {
public function __set($key, $value) {
throw new Exception('Can't modify property directly.');
}
}
然而,无论是否公开,这都会阻止对财产进行修改。
答案 2 :(得分:1)
所以你可以做得更好 - 如果你有动态的字段数
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');
}
}
答案 3 :(得分:0)
<?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.