在PHP中模拟值类型结构类

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');

我唯一能想到的另一种方法是使用__set()方法,但情况更糟。你必须这样做,这太令人困惑了。

1
$obj = $obj->blah = 'foo';

最后,可能更容易使变量私有化并且不提供变元,因此更改变量的"枚举"值的唯一方法是创建一个新的变元:

1
2
echo $obj; //"banana"
$obj = new FruityEnum("cantaloupe");


对象总是通过引用传递。使它们作为副本传递的唯一方法是显式地使用clone关键字(是,无处不在)。

我的建议是使用一个数组,它是值类型,因此总是被复制。因为您可以将它用作关联数组(例如string->value),所以它也可能是一个对象。缺点是,当然,您不能使用方法(但这就像一个结构,所以您可能对此很满意)。然而,没有办法强制类型安全。

但是,老实说,有了所有的需求,似乎PHP不是你的语言。


我认为只有用PHP代码才能实现这个目标。

您无法控制PHP函数如何处理参数,我看不到如何确保按您所希望的方式处理所有内容,而无需更改PHP二进制文件和模块中的(较低级别)代码。

不过,那会很酷的:)


我认为最简单的方法是像Java那样执行它——让你的值类是不可变的,让所有的"修改"方法返回一个新的对象。