自动检查两个对象是否相等?

Auto-check equality of two objects?

提问人:Andrei Herford 提问时间:1/13/2016 最后编辑:Will VousdenAndrei Herford 更新时间:1/13/2016 访问量:123

问:

我需要检查两个PHP对象在相等值方面是否相等。当然,我可以轻松地将一个比较所有相关值的方法添加到类中。但是,具体类将在不久的将来发生变化,我想知道是否有任何自动化方法可以做到这一点。isEqualTo(...)

例:

class Contact {
    private name;       // String
    private phone;      // Int
    private someObject; // Custom Object

    public function getName() {
        return $this->name;
    }

    public function setName($newName) {
        $this->name = $newName;
    }


    public function getPhone() {
        return $this->phone;
    }

    public function setPhone($newPhone) {
        $this->phone = $newPhone;
    }


    public function getSomeObject() {
        return $this->someObject;
    }

    public function setSomeObject($newObj) {
        $this->someObject = $newObj;
    }


    // Manual Solution 
    public function isEqualTo($contact) {
         result  = $this->name == $contact->getName();
         result &= $this->phone == $contact->getPhone();

         result &= $this->someObject == $contact->getSomeObject();

         return result;
    }
} 

这显然会起作用。当然,我知道比较的局限性(需要确切的某个对象才能为真),但这没关系。someObject

但是,该课程将在不久的将来扩展。每次我向类添加新的属性/值时,我都必须将它们添加到其中。没什么大不了的,但有点麻烦。ContactisEqualTo

那么,有没有办法自动实现所有可用的公共属性呢?isEqualTo

我发现,但这些方法不适用于 getter 和 setter,而仅适用于可以直接访问的 var。get_class_varsget_object_vars

我发现但这返回了所有方法,而不仅仅是 getter 和 setter。当然,过滤方法名称 and 会起作用,但这更像是一种黑客攻击,而不是“漂亮而干净”的解决方案。get_class_methodesget...set...

总之:有没有“正确”的方法可以自动检查两个PHP对象是否相等?

PHP 对象 相等

评论


答:

4赞 VolkerK 1/13/2016 #1

我不会说这是“正确”的方式,但是由于您不想实现/维护自己的比较函数/方法,因此您可能会对php的默认行为感兴趣,包括受保护/私有属性的比较:

<?php
class Foo {
    private $x,$y,$z;
    public function __construct($x,$y,$z) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }
}

$f1 = new Foo(1,2,3);
$f2 = new Foo(4,5,6);
$f3 = new Foo(1,2,3);

var_dump(
    $f1==$f2,
    $f1==$f3
);

指纹

bool(false)
bool(true)

这对你来说可能足够,也可能不够。


正如 Alma Do 所指出的,循环引用,例如

<?php
class Foo {
    private $x,$y,$z;
    public function __construct($x,$y,$z) {
        $this->x = $x;
        $this->y = $y;
        $this->z = $z;
    }

    public function setZ($z) {
        $this->z = $z;
    }
}


$f1 = new Foo(1,2,3);
$f2 = new Foo(4,5,6);
$f3 = new Foo(1,2,3);

$f1->setZ($f3);
$f3->setZ($f1);


var_dump(
    $f1==$f2,
    $f1==$f3
);

将导致 .Fatal error: Nesting level too deep - recursive dependency?

评论

1赞 Alma Do 1/13/2016
这将在循环引用上失败(以一种糟糕的方式,导致致命错误)。使用时要记住这一点很重要。
0赞 VolkerK 1/13/2016
事实上。将此添加到答案中(还有其他问题,但这可能是最明显和最戏剧性的)。
0赞 Alma Do 1/13/2016
好吧,“循环引用”——我的意思是不仅仅是狭义的对象情况。不能有跨对象引用,甚至可以有跨属性(或内联属性)递归。没有嵌套对象的示例案例是数组,如本代码段所示。所以你的样本是有效的,我只是注意到遍历比较的递归结构在 PHP 中效果不佳。缓解这种情况的常用方法是使用 DFS 和自定义用户函数(通过对象的反射)
0赞 doubleB 1/13/2016 #2

你可以使用 Reflection 来做到这一点,但我认为这不是一个好主意。也许serialize()是一个更好的解决方案?

function isEquals(self $obj){
return serialize($obj)===serialize($this)
}