【发布时间】:2010-12-01 23:40:18
【问题描述】:
有没有办法在 PHP 中模拟结构类?即一个通过值而不是通过引用传递的类,所以它仍然可以被类型提示......
如果是这样,可以使用哪些不同的技术?最好的技术是什么?
如果可能的话,您显然可以为 PHP 创建一个完全类型安全的层,有这样的层吗?有没有人有这方面的经验?
【问题讨论】:
标签: php types structure type-safety
有没有办法在 PHP 中模拟结构类?即一个通过值而不是通过引用传递的类,所以它仍然可以被类型提示......
如果是这样,可以使用哪些不同的技术?最好的技术是什么?
如果可能的话,您显然可以为 PHP 创建一个完全类型安全的层,有这样的层吗?有没有人有这方面的经验?
【问题讨论】:
标签: php types structure type-safety
我认为最简单的方法是像 java 那样做——让你的值类是不可变的,并让所有“修改”方法返回一个新对象。
【讨论】:
我认为你无法实现这个目标,只有使用 PHP 代码。
您无法控制 PHP 函数如何处理参数,我看不出您如何确保一切都按照您想要的方式处理,而无需更改 PHP 二进制文件和模块中的(低级)代码.
不过会很酷:)
【讨论】:
对象总是通过引用传递。使它们作为副本传递的唯一方法是显式使用 clone 关键字(是的,无处不在)。
我的建议是使用数组,它是值类型,因此总是被复制。由于您可以将其用作关联数组(例如字符串 -> 值),因此它也可以是一个对象。当然,缺点是你不能使用方法(但这就像一个结构,所以你可能会对此感到满意)。然而,没有办法强制执行类型安全。
但是说实话,根据您的所有要求,PHP 不是您喜欢的语言。
【讨论】:
我正在玩弄匿名的建议,让对象的任何突变都返回一个新对象,这可行,但很尴尬。
<?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;
}
}
现在来测试一下:
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"
可以,但是你必须使用一种奇怪的方式来改变对象:
$obj->set($obj, 'foo');
我能想到的唯一其他方法是使用__set() 方法,但那更糟。您必须这样做,这非常令人困惑。
$obj = $obj->blah = 'foo';
最后,将变量设为私有且不提供修改器可能更容易,因此更改变量“枚举”值的唯一方法是创建一个新变量:
echo $obj; // "banana"
$obj = new FruityEnum("cantaloupe");
【讨论】: