代码之家  ›  专栏  ›  技术社区  ›  NDM

在PHP中模拟值类型结构类

  •  2
  • NDM  · 技术社区  · 16 年前

    有没有办法在PHP中模拟一个结构类?即通过值而不是引用传递的类,因此它仍然可以被类型暗示…

    如果是这样,可以使用什么不同的技术?最好的技巧是什么?

    如果这是可能的,您显然可以为PHP创建一个完全类型安全的层,是否有这样的层?有人对此有经验吗?

    4 回复  |  直到 16 年前
        1
  •  1
  •   ryeguy    16 年前

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

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

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

        2
  •  1
  •   Anonymous    16 年前

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

        3
  •  1
  •   Nicolas    16 年前

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

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

    不过,那会很酷的:)

        4
  •  1
  •   nickf    16 年前

    我在玩弄匿名者的建议,让对象的任何变化都返回一个新对象,这是可行的,但很尴尬。

    <?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");
    
    推荐文章