php - PHP 中的常量非修改对象引用

标签 php oop

这不是关于实际代码的问题,它只是为了讨论。在我看来,能够将对象作为常量引用传递会很好。

$c = Coordinate;
unsafe_func($c); // this should be ok
unsafe_func(... constant reference ... $c); // this should fail on write to $c

我知道有一个选项可以传递对象的克隆,例如 set(clone $c)这将保留我原来的 $c未被 unsafe_func() 修改,但是如果我想要一个单一的对象实例呢?

我想到的是一个使用 __set() 的包装类(代码:https://gist.github.com/904897)和 __get()魔术方法,在每个 __set() 上抛出异常称呼。它允许我这样做:

class CoordinateConst extends stdConst {};
unsafe_func(new CoordinateConst($c)); // exception: can not be modified!

我不喜欢该解决方案的一点是,通过引入 CoordinateConst,我必须删除 Coordinate 类型提示。但是如果我扩展坐标类,__set()不为可见属性调用方法。

问题:是否有更常见的方法来执行此操作,或者您宁愿在任何情况下都避免使用此类代码(通过传递对象克隆、包装 unsafe_func 调用或其他方式)?

最佳答案

您的解决方案有效地防止了公共(public)属性被写入。如果坐标具有以下功能,则坐标将不是常量引用:

public function setX($x) {
    $this->x = $x;
}

另一种方法(但更多代码取决于您想要执行它的频率)是创建类的只读版本。

我知道在 Java 和 C# 中它通常应用于集合。 C# 有一个 ReadOnlyCollection<T> ,这只是一个包装器/代理,就像您在那里所做的一样。

所以我解决这个问题的方法是创建:

class ReadOnlyCoordinate { 
    private $coordinate;

    public function __construct(Coordinate $coordinate) {
        $this->coordinate = $coordinate;
    }

    public function getX() {
        return $this->coordinate->getX();
    }

当然,您可以扩展 Coordinate,然后对设置任何属性的函数抛出异常。


然后从整体上看这个问题,如果你不想让 Coordinate 成员/setter 暴露给 unsafe_func , 那么也许你只能发送所需的数据。这当然取决于它需要多少坐标数据。

例如

unsafe_func($coordinate->getRequiredData());

但是如果您需要大量数据,就会变得很麻烦。

关于php - PHP 中的常量非修改对象引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5560253/

相关文章:

php - 在 Sphinx 中使用 SPH_SORT_RELEVANCE 时,权重相等的结果如何排序?

javascript - 在 JavaScript 中将 canvas 设为全局对象是一个好习惯吗?

c++ - 另一个 undefined reference 错误

javascript - js + lodash js debound + php : debound function lodash is not working

php - 如何检查数组(php)中的任何项目是否在表(mysql)中

c# - 具有不断变化的数据类型的管道在架构上是否合理?

php - 传递 IoC 容器的正确方法

php - 如何避免将我的 $registry 容器手动传递到我创建的每个新类的构造函数中?

php - 每个表单上的 Laravel 5.2 CSRF 字段?

php - 1对1随机配对