Emulating a value type structure class in PHP
有没有办法在PHP中模拟一个结构类?即通过值而不是引用传递的类,因此它仍然可以被类型提示…
如果是这样,可以使用什么不同的技术?最好的技巧是什么?
如果这是可能的,您显然可以为PHP创建一个完全类型安全的层,是否有这样的层?有人对此有经验吗?
我在玩弄匿名者的建议,让对象的任何变化都返回一个新对象,这很有效,但很尴尬。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | <?php class FruityEnum { private $valid = array("apple","banana","cantaloupe"); private $value; function __construct($val) { if (in_array($val, $this->valid)) { $this->value = $val; } else { throw new Exception("Invalid value"); } } function __set($var, $val) { throw new Exception("Use set()!!"); } function set(FruityEnum &$obj, $val) { $obj = new FruityEnum($val); } function __get($var) { //everything returns the value... return $this->value; } function __toString() { return $this->value; } } |
现在测试一下:
1 2 3 4 5 6 7 8 9 10 | function mutate(FruityEnum $obj) { // type hinting! $obj->set($obj, 'banana'); return $obj; } $x = new FruityEnum('apple'); echo $x; //"apple" $y = mutate($x); echo $x // still"apple" . $y //"banana" |
它起作用,但你必须用一种奇怪的方式来改变物体:
1 | $obj->set($obj, 'foo'); |
我唯一能想到的另一种方法是使用
1 | $obj = $obj->blah = 'foo'; |
最后,可能更容易使变量私有化并且不提供变元,因此更改变量的"枚举"值的唯一方法是创建一个新的变元:
1 2 | echo $obj; //"banana" $obj = new FruityEnum("cantaloupe"); |
对象总是通过引用传递。使它们作为副本传递的唯一方法是显式地使用
我的建议是使用一个数组,它是值类型,因此总是被复制。因为您可以将它用作关联数组(例如string->value),所以它也可能是一个对象。缺点是,当然,您不能使用方法(但这就像一个结构,所以您可能对此很满意)。然而,没有办法强制类型安全。
但是,老实说,有了所有的需求,似乎PHP不是你的语言。
我认为只有用PHP代码才能实现这个目标。
您无法控制PHP函数如何处理参数,我看不到如何确保按您所希望的方式处理所有内容,而无需更改PHP二进制文件和模块中的(较低级别)代码。
不过,那会很酷的:)
我认为最简单的方法是像Java那样执行它——让你的值类是不可变的,让所有的"修改"方法返回一个新的对象。